Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
PerformanceProfiler.h
Go to the documentation of this file.
1/**
2 * @file PerformanceProfiler.h
3 * @brief Performance profiler for ATS Visual Scripting node execution (Phase 5).
4 * @author Olympe Engine
5 * @date 2026-03-09
6 *
7 * @details
8 * PerformanceProfiler is a singleton that collects per-node execution
9 * metrics across frames. It is opt-in: profiling only starts when
10 * BeginProfiling() is called, and stops with StopProfiling().
11 *
12 * C++14 compliant — no std::optional, structured bindings, std::filesystem.
13 */
14
15#pragma once
16
17#include <string>
18#include <vector>
19#include <unordered_map>
20#include <mutex>
21#include <cstdint>
22#include <chrono>
23
24namespace Olympe {
25
26// ============================================================================
27// Supporting structures
28// ============================================================================
29
30/**
31 * @struct NodeExecutionMetrics
32 * @brief Accumulated per-node execution statistics.
33 */
35 int nodeID = -1;
36 std::string nodeName;
37 float executionTimeMs = 0.0f; ///< Last recorded execution time (ms)
38 uint64_t executionCount = 0; ///< Total number of executions
39 float avgTimeMs = 0.0f; ///< Running average execution time (ms)
40 float maxTimeMs = 0.0f; ///< Maximum observed execution time (ms)
41 float totalTimeMs = 0.0f; ///< Total accumulated time (ms)
42};
43
44/**
45 * @struct FrameProfile
46 * @brief Snapshot of all node metrics for a single frame.
47 */
50 float totalFrameTimeMs = 0.0f;
51 std::vector<NodeExecutionMetrics> nodeMetrics;
52};
53
54// ============================================================================
55// PerformanceProfiler
56// ============================================================================
57
58/**
59 * @class PerformanceProfiler
60 * @brief Singleton performance profiler for VS graph node execution.
61 *
62 * @details
63 * Usage pattern (from VSGraphExecutor):
64 * @code
65 * PerformanceProfiler::Get().BeginNodeExecution(node->nodeID, node->nodeName);
66 * // ... execute node ...
67 * PerformanceProfiler::Get().EndNodeExecution(node->nodeID);
68 * @endcode
69 *
70 * Usage pattern (from TaskSystem / game loop):
71 * @code
72 * PerformanceProfiler::Get().BeginFrame();
73 * // ... process all task runners ...
74 * PerformanceProfiler::Get().EndFrame();
75 * @endcode
76 *
77 * Meyers singleton pattern (local static in Get()).
78 * Thread-safe via std::mutex.
79 */
81public:
82
83 /**
84 * @brief Returns the singleton instance (Meyers pattern).
85 */
86 static PerformanceProfiler& Get();
87
88 // -----------------------------------------------------------------------
89 // Profiling lifecycle
90 // -----------------------------------------------------------------------
91
92 /**
93 * @brief Enables profiling. Must be called before BeginFrame().
94 */
95 void BeginProfiling();
96
97 /**
98 * @brief Disables profiling and optionally clears accumulated data.
99 */
100 void StopProfiling();
101
102 /**
103 * @brief Returns true if profiling is currently enabled.
104 */
105 bool IsProfiling() const;
106
107 // -----------------------------------------------------------------------
108 // Frame lifecycle
109 // -----------------------------------------------------------------------
110
111 /**
112 * @brief Marks the start of a new frame.
113 * Clears the per-frame node timing accumulators.
114 */
115 void BeginFrame();
116
117 /**
118 * @brief Marks the end of the current frame.
119 * Commits the frame data to history.
120 */
121 void EndFrame();
122
123 // -----------------------------------------------------------------------
124 // Node instrumentation
125 // -----------------------------------------------------------------------
126
127 /**
128 * @brief Records the start time for a node execution.
129 * @param nodeID ID of the node.
130 * @param nodeName Human-readable node name (used on first call).
131 */
132 void BeginNodeExecution(int nodeID, const std::string& nodeName);
133
134 /**
135 * @brief Records the end time for a node execution and updates metrics.
136 * @param nodeID ID of the node (must match the last BeginNodeExecution call).
137 */
138 void EndNodeExecution(int nodeID);
139
140 // -----------------------------------------------------------------------
141 // Data access
142 // -----------------------------------------------------------------------
143
144 /**
145 * @brief Returns the current (in-progress) frame profile.
146 */
148
149 /**
150 * @brief Returns up to @p count most recent completed frame profiles.
151 * @param count Maximum number of frames to return (0 = all).
152 */
153 std::vector<FrameProfile> GetFrameHistory(int count = 0) const;
154
155 /**
156 * @brief Returns accumulated lifetime metrics sorted by avgTimeMs descending.
157 */
158 std::vector<NodeExecutionMetrics> GetHotspots() const;
159
160 /**
161 * @brief Clears all accumulated data and history.
162 */
163 void Clear();
164
165 /**
166 * @brief Exports the frame history to a CSV file.
167 * @param path Destination file path (must be writable).
168 * @return true on success, false on file open error.
169 */
170 bool SaveToFile(const std::string& path) const;
171
172 // -----------------------------------------------------------------------
173 // Constants
174 // -----------------------------------------------------------------------
175
176 /// Number of frames kept in the rolling history buffer.
177 static const int MAX_FRAME_HISTORY = 120;
178
179 /// Hotspot threshold (ms) — nodes above this are flagged.
180 static constexpr float HOTSPOT_THRESHOLD_MS = 1.0f;
181
182private:
183
186
187 // Non-copyable, non-movable
190
191 // -----------------------------------------------------------------------
192 // Internal state
193 // -----------------------------------------------------------------------
194
195 mutable std::mutex m_mutex;
196
197 bool m_profiling = false;
199
200 /// Per-frame timing: node ID -> start time
201 std::unordered_map<int, std::chrono::steady_clock::time_point> m_nodeStartTimes;
202
203 /// Accumulated per-frame node metrics (reset each BeginFrame)
204 std::unordered_map<int, NodeExecutionMetrics> m_frameNodeMetrics;
205
206 /// Lifetime metrics per node
207 std::unordered_map<int, NodeExecutionMetrics> m_lifetimeMetrics;
208
209 /// Rolling frame history buffer
210 std::vector<FrameProfile> m_frameHistory;
211
212 /// Frame start time
213 std::chrono::steady_clock::time_point m_frameStartTime;
214};
215
216} // namespace Olympe
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Singleton performance profiler for VS graph node execution.
static PerformanceProfiler & Get()
Returns the singleton instance (Meyers pattern).
bool IsProfiling() const
Returns true if profiling is currently enabled.
std::unordered_map< int, NodeExecutionMetrics > m_lifetimeMetrics
Lifetime metrics per node.
void BeginNodeExecution(int nodeID, const std::string &nodeName)
Records the start time for a node execution.
FrameProfile GetCurrentFrame() const
Returns the current (in-progress) frame profile.
std::unordered_map< int, std::chrono::steady_clock::time_point > m_nodeStartTimes
Per-frame timing: node ID -> start time.
std::unordered_map< int, NodeExecutionMetrics > m_frameNodeMetrics
Accumulated per-frame node metrics (reset each BeginFrame)
void Clear()
Clears all accumulated data and history.
void BeginProfiling()
Enables profiling.
std::vector< FrameProfile > GetFrameHistory(int count=0) const
Returns up to count most recent completed frame profiles.
std::vector< NodeExecutionMetrics > GetHotspots() const
Returns accumulated lifetime metrics sorted by avgTimeMs descending.
bool SaveToFile(const std::string &path) const
Exports the frame history to a CSV file.
void EndNodeExecution(int nodeID)
Records the end time for a node execution and updates metrics.
static constexpr float HOTSPOT_THRESHOLD_MS
Hotspot threshold (ms) — nodes above this are flagged.
std::chrono::steady_clock::time_point m_frameStartTime
Frame start time.
void EndFrame()
Marks the end of the current frame.
void StopProfiling()
Disables profiling and optionally clears accumulated data.
PerformanceProfiler & operator=(const PerformanceProfiler &)=delete
static const int MAX_FRAME_HISTORY
Number of frames kept in the rolling history buffer.
PerformanceProfiler(const PerformanceProfiler &)=delete
std::vector< FrameProfile > m_frameHistory
Rolling frame history buffer.
void BeginFrame()
Marks the start of a new frame.
< Provides AssetID and INVALID_ASSET_ID
Snapshot of all node metrics for a single frame.
std::vector< NodeExecutionMetrics > nodeMetrics
Accumulated per-node execution statistics.
float maxTimeMs
Maximum observed execution time (ms)
uint64_t executionCount
Total number of executions.
float executionTimeMs
Last recorded execution time (ms)
float totalTimeMs
Total accumulated time (ms)
float avgTimeMs
Running average execution time (ms)