13#ifndef APP_PROFILER_HPP
14#define APP_PROFILER_HPP
28 using Clock = std::chrono::high_resolution_clock;
29 using TimePoint = Clock::time_point;
34 static void startQtInit() { instance().qtInitStart_ = Clock::now(); }
40 auto& inst = instance();
41 if (inst.qtInitStart_ != TimePoint{}) {
42 inst.qtInitTime_ += std::chrono::duration<double>(
43 Clock::now() - inst.qtInitStart_)
45 inst.qtInitStart_ = TimePoint{};
53 instance().windowCreationStart_ = Clock::now();
60 auto& inst = instance();
61 if (inst.windowCreationStart_ != TimePoint{}) {
62 inst.windowCreationTime_ +=
63 std::chrono::duration<double>(Clock::now() -
64 inst.windowCreationStart_)
66 inst.windowCreationStart_ = TimePoint{};
74 instance().frameRenderStart_ = Clock::now();
81 auto& inst = instance();
82 if (inst.frameRenderStart_ != TimePoint{}) {
83 inst.frameRenderTime_ +=
84 std::chrono::duration<double>(Clock::now() -
85 inst.frameRenderStart_)
87 inst.frameRenderCount_++;
88 inst.frameRenderStart_ = TimePoint{};
96 instance().eventLoopStart_ = Clock::now();
103 auto& inst = instance();
104 if (inst.eventLoopStart_ != TimePoint{}) {
105 inst.eventLoopTime_ += std::chrono::duration<double>(
106 Clock::now() - inst.eventLoopStart_)
108 inst.eventLoopStart_ = TimePoint{};
115 static void startCleanup() { instance().cleanupStart_ = Clock::now(); }
121 auto& inst = instance();
122 if (inst.cleanupStart_ != TimePoint{}) {
123 inst.cleanupTime_ += std::chrono::duration<double>(
124 Clock::now() - inst.cleanupStart_)
126 inst.cleanupStart_ = TimePoint{};
137 instance().cleanupDisplayPrepTime_ += seconds;
144 instance().cleanupDisplayProcessEventsTime_ += seconds;
151 instance().cleanupDisplayThreadStopTime_ += seconds;
158 instance().cleanupDisplayWorkerCleanupTime_ += seconds;
165 instance().cleanupAppBridgeCleanupTime_ += seconds;
175 instance().cleanupAppManualDestroyTime_ += seconds;
182 instance().cleanupAppDetachContainerTime_ += seconds;
189 instance().cleanupAppReleaseDisplayTime_ += seconds;
199 instance().cleanupAppContainerDeleteScheduleTime_ += seconds;
206 instance().cleanupAppProcessEventsTime_ += seconds;
213 const auto& inst = instance();
214 const double totalTime =
215 inst.qtInitTime_ + inst.windowCreationTime_ +
216 inst.eventLoopTime_ + inst.frameRenderTime_ + inst.cleanupTime_;
218 if (totalTime < 1e-9) {
220 <<
"\n--- Application Profiling Report (No data) ---";
224 const double avgFrameMs =
225 inst.frameRenderCount_ > 0
226 ? inst.frameRenderTime_ / inst.frameRenderCount_ * 1000.0
230 "\n--- Application Profiling Report ---\nQt "
231 "Initialization: %1s (%2%%)\n3D Window Creation: "
232 "%3s (%4%%)\nQt Event Loop: %5s (%6%%)\nFrame "
233 "Rendering: %7s (%8%%) (%9 frames, avg: "
234 "%10ms/frame)\nCleanup: %11s "
235 "(%12%%)\n------------------------\nTotal Application "
237 .arg(inst.qtInitTime_, 9,
'f', 4)
238 .arg(inst.qtInitTime_ / totalTime * 100.0, 5,
'f', 1)
239 .arg(inst.windowCreationTime_, 9,
'f', 4)
240 .arg(inst.windowCreationTime_ / totalTime * 100.0, 5,
'f',
242 .arg(inst.eventLoopTime_, 9,
'f', 4)
243 .arg(inst.eventLoopTime_ / totalTime * 100.0, 5,
'f', 1)
244 .arg(inst.frameRenderTime_, 9,
'f', 4)
245 .arg(inst.frameRenderTime_ / totalTime * 100.0, 5,
'f', 1)
246 .arg(inst.frameRenderCount_)
247 .arg(avgFrameMs, 0,
'f', 4)
248 .arg(inst.cleanupTime_, 9,
'f', 4)
249 .arg(inst.cleanupTime_ / totalTime * 100.0, 5,
'f', 1)
250 .arg(totalTime, 9,
'f', 4);
251 qDebug().noquote() << msg;
253 if (inst.cleanupTime_ > 1e-9) {
254 const QString cleanupMsg =
256 "\n--- Cleanup Breakdown ---\nDisplay Prep: "
257 "%1s (%2%%)\nDisplay processEvents:%3s "
258 "(%4%%)\nDisplay Thread Stop:%5s (%6%%)\nDisplay "
259 "Worker Cleanup:%7s (%8%%)\nBridge "
260 "Cleanup*: %9s (%10%%)\nManual "
261 "Destroy: %11s (%12%%)\nApp processEvents: "
262 "%13s (%14%%)\n*Bridge Cleanup includes Display "
263 "sub-phases\n------------------------")
264 .arg(inst.cleanupDisplayPrepTime_, 9,
'f', 4)
265 .arg(inst.cleanupDisplayPrepTime_ / inst.cleanupTime_ *
268 .arg(inst.cleanupDisplayProcessEventsTime_, 9,
'f', 4)
269 .arg(inst.cleanupDisplayProcessEventsTime_ /
270 inst.cleanupTime_ * 100.0,
272 .arg(inst.cleanupDisplayThreadStopTime_, 9,
'f', 4)
273 .arg(inst.cleanupDisplayThreadStopTime_ /
274 inst.cleanupTime_ * 100.0,
276 .arg(inst.cleanupDisplayWorkerCleanupTime_, 9,
'f', 4)
277 .arg(inst.cleanupDisplayWorkerCleanupTime_ /
278 inst.cleanupTime_ * 100.0,
280 .arg(inst.cleanupAppBridgeCleanupTime_, 9,
'f', 4)
281 .arg(inst.cleanupAppBridgeCleanupTime_ /
282 inst.cleanupTime_ * 100.0,
284 .arg(inst.cleanupAppManualDestroyTime_, 9,
'f', 4)
285 .arg(inst.cleanupAppManualDestroyTime_ /
286 inst.cleanupTime_ * 100.0,
288 .arg(inst.cleanupAppProcessEventsTime_, 9,
'f', 4)
289 .arg(inst.cleanupAppProcessEventsTime_ /
290 inst.cleanupTime_ * 100.0,
292 qDebug().noquote() << cleanupMsg;
294 if (inst.cleanupAppManualDestroyTime_ > 1e-9) {
295 const QString manualDestroyMsg =
297 "\n--- Manual Destroy Breakdown ---\nDetach "
298 "Container: %1s (%2%%)\nRelease Display: %3s "
299 "(%4%%)\nContainer Delete: %5s "
300 "(%6%%)\n------------------------")
301 .arg(inst.cleanupAppDetachContainerTime_, 9,
'f', 4)
302 .arg(inst.cleanupAppDetachContainerTime_ /
303 inst.cleanupAppManualDestroyTime_ * 100.0,
305 .arg(inst.cleanupAppReleaseDisplayTime_, 9,
'f', 4)
306 .arg(inst.cleanupAppReleaseDisplayTime_ /
307 inst.cleanupAppManualDestroyTime_ * 100.0,
309 .arg(inst.cleanupAppContainerDeleteScheduleTime_, 9,
311 .arg(inst.cleanupAppContainerDeleteScheduleTime_ /
312 inst.cleanupAppManualDestroyTime_ * 100.0,
314 qDebug().noquote() << manualDestroyMsg;
323 auto& inst = instance();
324 inst.qtInitTime_ = 0.0;
325 inst.windowCreationTime_ = 0.0;
326 inst.eventLoopTime_ = 0.0;
327 inst.frameRenderTime_ = 0.0;
328 inst.cleanupTime_ = 0.0;
329 inst.cleanupDisplayPrepTime_ = 0.0;
330 inst.cleanupDisplayProcessEventsTime_ = 0.0;
331 inst.cleanupDisplayThreadStopTime_ = 0.0;
332 inst.cleanupDisplayWorkerCleanupTime_ = 0.0;
333 inst.cleanupAppBridgeCleanupTime_ = 0.0;
334 inst.cleanupAppManualDestroyTime_ = 0.0;
335 inst.cleanupAppProcessEventsTime_ = 0.0;
336 inst.cleanupAppDetachContainerTime_ = 0.0;
337 inst.cleanupAppReleaseDisplayTime_ = 0.0;
338 inst.cleanupAppContainerDeleteScheduleTime_ = 0.0;
339 inst.frameRenderCount_ = 0;
340 inst.qtInitStart_ = TimePoint{};
341 inst.windowCreationStart_ = TimePoint{};
342 inst.eventLoopStart_ = TimePoint{};
343 inst.frameRenderStart_ = TimePoint{};
344 inst.cleanupStart_ = TimePoint{};
358 double qtInitTime_ = 0.0;
359 double windowCreationTime_ = 0.0;
360 double eventLoopTime_ = 0.0;
361 double frameRenderTime_ = 0.0;
362 double cleanupTime_ = 0.0;
363 double cleanupDisplayPrepTime_ = 0.0;
364 double cleanupDisplayProcessEventsTime_ = 0.0;
365 double cleanupDisplayThreadStopTime_ = 0.0;
366 double cleanupDisplayWorkerCleanupTime_ = 0.0;
367 double cleanupAppBridgeCleanupTime_ = 0.0;
368 double cleanupAppManualDestroyTime_ = 0.0;
369 double cleanupAppProcessEventsTime_ = 0.0;
370 double cleanupAppDetachContainerTime_ = 0.0;
371 double cleanupAppReleaseDisplayTime_ = 0.0;
372 double cleanupAppContainerDeleteScheduleTime_ = 0.0;
373 std::size_t frameRenderCount_ = 0;
375 TimePoint qtInitStart_{};
376 TimePoint windowCreationStart_{};
377 TimePoint eventLoopStart_{};
378 TimePoint frameRenderStart_{};
379 TimePoint cleanupStart_{};
Global application profiler for measuring non-physics phases.
static void addCleanupDisplayProcessEvents(double seconds)
Adds measured time spent in Display cleanup processEvents.
static void addCleanupAppProcessEvents(double seconds)
Adds measured time spent in AppManager cleanup processEvents.
static void startQtInit()
Starts timing Qt initialization.
static void stopQtInit()
Stops timing Qt initialization.
static void addCleanupAppManualDestroy(double seconds)
Adds measured time for manual destroy operations.
static void startEventLoop()
Starts timing the Qt event loop.
static void printReport()
Prints the profiling report.
static void addCleanupDisplayPrep(double seconds)
Adds measured time for Display cleanup preparation.
static void addCleanupDisplayWorkerCleanup(double seconds)
Adds measured time for physics worker cleanup.
static void stopFrameRender()
Stops timing a frame render.
static void addCleanupAppBridgeCleanup(double seconds)
Adds measured time spent in bridge/display cleanup call.
static void addCleanupAppDetachContainer(double seconds)
Adds measured time for detaching the display container.
static void startFrameRender()
Starts timing a frame render.
static void stopEventLoop()
Stops timing the Qt event loop.
static void reset()
Resets all profiling data.
static void startCleanup()
Starts timing cleanup.
static void addCleanupAppContainerDeleteSchedule(double seconds)
Adds measured time for container delete action.
static void stopWindowCreation()
Stops timing 3D window creation.
static void addCleanupDisplayThreadStop(double seconds)
Adds measured time for stopping the physics thread.
static void addCleanupAppReleaseDisplay(double seconds)
Adds measured time for explicit display release.
static void startWindowCreation()
Starts timing 3D window creation.
static void stopCleanup()
Stops timing cleanup.
Namespace for application-wide utility functions, primarily for exception handling.