From bf83b9bfde0b1e851a1bda7f610b71facd0b8d23 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sat, 31 Jan 2026 20:00:40 +0100 Subject: [PATCH] Base: Add TimeTracker (#26305) * Base: Add TimeTracker This adds TimeTracker utility that can be used to orchestrate code with time measurements in an easy way and detect performance issues. * Update src/Base/TimeInfo.h Co-authored-by: Chris Hennes --------- Co-authored-by: Chris Hennes --- src/Base/TimeInfo.h | 71 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/Base/TimeInfo.h b/src/Base/TimeInfo.h index 2bcb330916..a44bd122d5 100644 --- a/src/Base/TimeInfo.h +++ b/src/Base/TimeInfo.h @@ -27,10 +27,13 @@ #ifndef BASE_TIMEINFO_H #define BASE_TIMEINFO_H +#include + #include #include #include -#include + +#include "Console.h" namespace Base { @@ -130,6 +133,72 @@ public: } }; // class TimeElapsed +/** + * @class TimeTracker + * @brief A utility class for tracking time intervals and logging checkpoints. + * + * This class facilitates time tracking by recording named checkpoints and + * calculating time intervals between them. It logs the time elapsed between + * checkpoints and the total time since the start. The time tracking automatically + * begins upon object instantiation and ends when the object is destroyed. + * + * The recommended way to use this class for performance optimization is through + * manual bisection. If a specific operation (e.g., a feature recompute) is slow, + * instrument the top-level function with a `TimeTracker` and several checkpoints. + * + * Once the most time-consuming segment is identified, move the instrumentation + * into the underlying functions called during that segment. Repeat this process + * recursively to isolate the root cause of the performance bottleneck. + * + * @code + * { + * Base::TimeTracker tracker("Document Loading"); + * // ... heavy computation ... + * tracker.checkpoint("Parsing XML"); + * // ... more work ... + * tracker.checkpoint("Building Topology"); + * // ... even more ... + * } // "finish" checkpoint is logged automatically here + * @endcode + */ +class TimeTracker +{ +public: + explicit TimeTracker(std::string name) + : name(std::move(name)) + , lastCheckpoint("start") + {} + + FC_DISABLE_COPY_MOVE(TimeTracker); + + void checkpoint(const std::string& checkpoint = "") + { + Console().log( + "(%s) %s -> %s: %f (%f total)\n", + name, + lastCheckpoint, + checkpoint, + TimeElapsed::diffTimeF(lastCheckpointTime), + TimeElapsed::diffTimeF(start) + ); + + lastCheckpoint = checkpoint; + lastCheckpointTime.setCurrent(); + } + + ~TimeTracker() + { + checkpoint("finish"); + } + +private: + std::string name; + std::string lastCheckpoint; + + TimeElapsed start; + TimeElapsed lastCheckpointTime; +}; + } // namespace Base #endif // BASE_TIMEINFO_H