# HG changeset patch # User Peter Nelson # Date 2024-01-21 18:38:40 # Node ID cfa82395f2ba694f85e0d402400d0ba3503a2820 # Parent d4a14037f1658a7ae0aeaafa1a162c82f2026b75 Codechange: Replace C-style TICC/TOCC macros with C++ RAII implementation. (#11857) Usage is more robust, and will always include timing when the TicToc object goes out of scope. diff --git a/src/debug.h b/src/debug.h --- a/src/debug.h +++ b/src/debug.h @@ -63,44 +63,38 @@ std::string GetDebugString(); /* Shorter form for passing filename and linenumber */ #define FILE_LINE __FILE__, __LINE__ -/** - * Used for profiling. - * +/** TicToc profiling. * Usage: - * TIC(); - * --Do your code-- - * TOC("A name", 1); - * - * When you run the TIC() / TOC() multiple times, you can increase the '1' - * to only display average stats every N values. Some things to know: - * - * for (int i = 0; i < 5; i++) { - * TIC(); - * --Do your code-- - * TOC("A name", 5); - * } - * - * Is the correct usage for multiple TIC() / TOC() calls. - * - * TIC() / TOC() creates its own block, so make sure not the mangle - * it with another block. - * - * The output is counted in microseconds. Mainly useful for local optimisations. - **/ -#define TIC() {\ - auto _start_ = std::chrono::high_resolution_clock::now();\ - static uint64_t _sum_ = 0;\ - static uint32_t _i_ = 0; + * static TicToc::State state("A name", 1); + * TicToc tt(state); + * --Do your code-- + */ +struct TicToc { + /** Persistent state for TicToc profiling. */ + struct State { + const std::string_view name; + const uint32_t max_count; + uint32_t count = 0; + uint64_t chrono_sum = 0; + + constexpr State(std::string_view name, uint32_t max_count) : name(name), max_count(max_count) { } + }; -#define TOC(str, _count_)\ - _sum_ += (std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - _start_)).count();\ - if (++_i_ == _count_) {\ - Debug(misc, 0, "[{}] {} us [avg: {:.1f} us]", str, _sum_, _sum_/(double)_i_);\ - _i_ = 0;\ - _sum_ = 0;\ - }\ -} + State &state; + std::chrono::high_resolution_clock::time_point chrono_start; ///< real time count. + + inline TicToc(State &state) : state(state), chrono_start(std::chrono::high_resolution_clock::now()) { } + inline ~TicToc() + { + this->state.chrono_sum += (std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - this->chrono_start)).count(); + if (++this->state.count == this->state.max_count) { + Debug(misc, 0, "[{}] {} us [avg: {:.1f} us]", this->state.name, this->state.chrono_sum, this->state.chrono_sum / static_cast(this->state.count)); + this->state.count = 0; + this->state.chrono_sum = 0; + } + } +}; void ShowInfoI(const std::string &str); #define ShowInfo(format_string, ...) ShowInfoI(fmt::format(FMT_STRING(format_string), ## __VA_ARGS__))