Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
ProfilerPanel.cpp
Go to the documentation of this file.
1/**
2 * @file ProfilerPanel.cpp
3 * @brief Implementation of ProfilerPanel (Phase 5).
4 * @author Olympe Engine
5 * @date 2026-03-09
6 *
7 * @details C++14 compliant.
8 */
9
10#include "ProfilerPanel.h"
11#include "PerformanceProfiler.h"
12
13#include "../third_party/imgui/imgui.h"
14
15#include <ctime>
16#include <string>
17#include <vector>
18#include <algorithm>
19#include <cstring>
20
21namespace Olympe {
22
23// ============================================================================
24// Constructor / Destructor
25// ============================================================================
26
30
34
38
42
43// ============================================================================
44// Render
45// ============================================================================
46
48{
49 if (!m_visible)
50 return;
51
52 ImGui::Begin("Profiler", &m_visible);
53
55 ImGui::Separator();
57 ImGui::Separator();
59
60 ImGui::End();
61}
62
63// ============================================================================
64// Controls toolbar
65// ============================================================================
66
68{
70
71 if (!prof.IsProfiling())
72 {
73 if (ImGui::Button("▶ Start Profiling"))
74 prof.BeginProfiling();
75 }
76 else
77 {
78 if (ImGui::Button("⏹ Stop Profiling"))
79 prof.StopProfiling();
80 }
81
82 ImGui::SameLine();
83
84 if (ImGui::Button("Clear##profClear"))
85 prof.Clear();
86
87 ImGui::SameLine();
88
89 // Export CSV
90 if (ImGui::Button("Export CSV"))
91 {
92 // Build timestamp filename
93 std::time_t t = std::time(nullptr);
94 char timeBuf[32];
95#ifdef _WIN32
96 struct tm tmInfo;
98 std::strftime(timeBuf, sizeof(timeBuf), "%Y%m%d_%H%M%S", &tmInfo);
99#else
100 struct tm tmInfo;
101 localtime_r(&t, &tmInfo);
102 std::strftime(timeBuf, sizeof(timeBuf), "%Y%m%d_%H%M%S", &tmInfo);
103#endif
104 std::string csvPath = std::string("profiler_export_") + timeBuf + ".csv";
105 if (prof.SaveToFile(csvPath))
106 ImGui::OpenPopup("ExportOK");
107 else
108 ImGui::OpenPopup("ExportFail");
109 }
110
111 if (ImGui::BeginPopup("ExportOK"))
112 {
113 ImGui::Text("CSV exported successfully.");
114 if (ImGui::Button("OK")) ImGui::CloseCurrentPopup();
115 ImGui::EndPopup();
116 }
117 if (ImGui::BeginPopup("ExportFail"))
118 {
119 ImGui::TextColored(ImVec4(1,0,0,1), "Export failed.");
120 if (ImGui::Button("OK")) ImGui::CloseCurrentPopup();
121 ImGui::EndPopup();
122 }
123
124 ImGui::SameLine();
125 ImGui::SetNextItemWidth(80.0f);
126 ImGui::SliderInt("Frames##profFrames", &m_historyCount, 10, 120);
127
128 ImGui::SameLine();
129 ImGui::Checkbox("Auto Scroll##profScroll", &m_autoScroll);
130}
131
132// ============================================================================
133// Frame timeline
134// ============================================================================
135
137{
138 ImGui::TextDisabled("Frame Timeline");
139
141 auto history = prof.GetFrameHistory(m_historyCount);
142
143 if (history.empty())
144 {
145 ImGui::TextDisabled("(no frame data — start profiling)");
146 return;
147 }
148
149 ImGui::BeginChild("FrameTimeline", ImVec2(0, 160), true,
151
152 for (size_t f = 0; f < history.size(); ++f)
153 {
154 const FrameProfile& frame = history[f];
155 ImGui::Text("F%llu (%.1fms):",
156 static_cast<unsigned long long>(frame.frameNumber),
157 frame.totalFrameTimeMs);
158
159 for (size_t n = 0; n < frame.nodeMetrics.size() && n < 8; ++n)
160 {
161 const NodeExecutionMetrics& m = frame.nodeMetrics[n];
162 bool isHot = m.executionTimeMs > PerformanceProfiler::HOTSPOT_THRESHOLD_MS;
163
164 // Simple ASCII bar
165 int barLen = static_cast<int>(m.executionTimeMs * 4.0f);
166 if (barLen < 1) barLen = 1;
167 if (barLen > 40) barLen = 40;
168
169 std::string bar(static_cast<size_t>(barLen), isHot ? '█' : '░');
170
171 if (isHot)
172 ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f),
173 " Node %-3d %-18s %s %.2fms",
174 m.nodeID, m.nodeName.c_str(),
175 bar.c_str(), m.executionTimeMs);
176 else
177 ImGui::Text(" Node %-3d %-18s %s %.2fms",
178 m.nodeID, m.nodeName.c_str(),
179 bar.c_str(), m.executionTimeMs);
180 }
181 }
182
183 if (m_autoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
184 ImGui::SetScrollHereY(1.0f);
185
186 ImGui::EndChild();
187}
188
189// ============================================================================
190// Hotspot table
191// ============================================================================
192
194{
195 ImGui::TextDisabled("Hotspot Table (sorted by avgTimeMs ▼)");
196
198 auto hotspots = prof.GetHotspots();
199
200 if (hotspots.empty())
201 {
202 ImGui::TextDisabled("(no data)");
203 return;
204 }
205
206 ImGui::BeginChild("HotspotTable", ImVec2(0, 180), true);
207
208 ImGui::Text("%-6s %-24s %9s %9s %9s",
209 "NodeID", "Name", "AvgMs", "MaxMs", "Count");
210 ImGui::Separator();
211
212 for (size_t i = 0; i < hotspots.size(); ++i)
213 {
216
217 if (isHot)
218 ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
219 "%-6d %-24s %9.3f %9.3f %9llu",
220 m.nodeID, m.nodeName.c_str(),
221 m.avgTimeMs, m.maxTimeMs, m.executionCount);
222 else
223 ImGui::Text("%-6d %-24s %9.3f %9.3f %9llu",
224 m.nodeID, m.nodeName.c_str(),
225 m.avgTimeMs, m.maxTimeMs, m.executionCount);
226 }
227
228 ImGui::EndChild();
229}
230
231} // namespace Olympe
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Performance profiler for ATS Visual Scripting node execution (Phase 5).
ImGui profiler panel for ATS VS node execution metrics (Phase 5).
Singleton performance profiler for VS graph node execution.
static PerformanceProfiler & Get()
Returns the singleton instance (Meyers pattern).
static constexpr float HOTSPOT_THRESHOLD_MS
Hotspot threshold (ms) — nodes above this are flagged.
int m_historyCount
Frames shown in timeline.
void Render()
Renders the profiler panel window.
< 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 avgTimeMs
Running average execution time (ms)