Actually, the PhaseTimer destructor approach won't work well since the phases don't have clean scope boundaries. Let me use a simpler macro-style approach.


Edit

// --- Phase timer ---
struct PhaseTimer {
    std::chrono::steady_clock::time_point start;
    const char* name;
    PhaseTimer(const char* n) : start(std::chrono::steady_clock::now()), name(n) {
        std::cerr << "  [TIMER] " << name << " started" << std::endl;
    }
    ~PhaseTimer() {
        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::steady_clock::now() - start).count();
        std::cerr << "  [TIMER] " << name << " completed in "
                  << elapsed / 1000 << "." << (elapsed % 1000) / 100 << "s" << std::endl;
    }
};

// --- Phase timer helper ---
static void log_elapsed(const char* phase, std::chrono::steady_clock::time_point start) {
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::steady_clock::now() - start).count();
    std::cerr << "  [" << ms/1000 << "." << (ms%1000)/100 << "s] " << phase << std::endl;
}
#define PHASE_START auto _phase_t = std::chrono::steady_clock::now()
#define PHASE_LOG(name) log_elapsed(name, _phase_t); _phase_t = std::chrono::steady_clock::now()