feat: Add benchmark logging system for performance analysis (closes #104)
Add Python API for capturing performance data to JSON files: - mcrfpy.start_benchmark() - start capturing frame data - mcrfpy.end_benchmark() - stop and return filename - mcrfpy.log_benchmark(msg) - add log message to current frame The benchmark system captures per-frame data including: - Frame timing (frame_time_ms, fps, timestamp) - Detailed timing breakdown (grid_render, entity_render, python, animation, fov) - Draw call and element counts - User log messages attached to frames Output JSON format supports analysis tools and includes: - Benchmark metadata (PID, timestamps, duration, total frames) - Full frame-by-frame metrics array Also refactors ProfilingMetrics from nested GameEngine struct to top-level struct for easier forward declaration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
219a559c35
commit
a7fef2aeb6
7 changed files with 551 additions and 59 deletions
124
src/GameEngine.h
124
src/GameEngine.h
|
|
@ -14,6 +14,70 @@
|
|||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
/**
|
||||
* @brief Performance profiling metrics structure
|
||||
*
|
||||
* Tracks frame timing, render counts, and detailed timing breakdowns.
|
||||
* Used by GameEngine, ProfilerOverlay (F3), and BenchmarkLogger.
|
||||
*/
|
||||
struct ProfilingMetrics {
|
||||
float frameTime = 0.0f; // Current frame time in milliseconds
|
||||
float avgFrameTime = 0.0f; // Average frame time over last N frames
|
||||
int fps = 0; // Frames per second
|
||||
int drawCalls = 0; // Draw calls per frame
|
||||
int uiElements = 0; // Number of UI elements rendered
|
||||
int visibleElements = 0; // Number of visible elements
|
||||
|
||||
// Detailed timing breakdowns (added for profiling system)
|
||||
float gridRenderTime = 0.0f; // Time spent rendering grids (ms)
|
||||
float entityRenderTime = 0.0f; // Time spent rendering entities (ms)
|
||||
float fovOverlayTime = 0.0f; // Time spent rendering FOV overlays (ms)
|
||||
float pythonScriptTime = 0.0f; // Time spent in Python callbacks (ms)
|
||||
float animationTime = 0.0f; // Time spent updating animations (ms)
|
||||
|
||||
// Grid-specific metrics
|
||||
int gridCellsRendered = 0; // Number of grid cells drawn this frame
|
||||
int entitiesRendered = 0; // Number of entities drawn this frame
|
||||
int totalEntities = 0; // Total entities in scene
|
||||
|
||||
// Frame time history for averaging
|
||||
static constexpr int HISTORY_SIZE = 60;
|
||||
float frameTimeHistory[HISTORY_SIZE] = {0};
|
||||
int historyIndex = 0;
|
||||
|
||||
void updateFrameTime(float deltaMs) {
|
||||
frameTime = deltaMs;
|
||||
frameTimeHistory[historyIndex] = deltaMs;
|
||||
historyIndex = (historyIndex + 1) % HISTORY_SIZE;
|
||||
|
||||
// Calculate average
|
||||
float sum = 0.0f;
|
||||
for (int i = 0; i < HISTORY_SIZE; ++i) {
|
||||
sum += frameTimeHistory[i];
|
||||
}
|
||||
avgFrameTime = sum / HISTORY_SIZE;
|
||||
fps = avgFrameTime > 0 ? static_cast<int>(1000.0f / avgFrameTime) : 0;
|
||||
}
|
||||
|
||||
void resetPerFrame() {
|
||||
drawCalls = 0;
|
||||
uiElements = 0;
|
||||
visibleElements = 0;
|
||||
|
||||
// Reset per-frame timing metrics
|
||||
gridRenderTime = 0.0f;
|
||||
entityRenderTime = 0.0f;
|
||||
fovOverlayTime = 0.0f;
|
||||
pythonScriptTime = 0.0f;
|
||||
animationTime = 0.0f;
|
||||
|
||||
// Reset per-frame counters
|
||||
gridCellsRendered = 0;
|
||||
entitiesRendered = 0;
|
||||
totalEntities = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class GameEngine
|
||||
{
|
||||
public:
|
||||
|
|
@ -76,64 +140,8 @@ public:
|
|||
std::map<std::string, std::shared_ptr<Timer>> timers;
|
||||
std::string scene;
|
||||
|
||||
// Profiling metrics
|
||||
struct ProfilingMetrics {
|
||||
float frameTime = 0.0f; // Current frame time in milliseconds
|
||||
float avgFrameTime = 0.0f; // Average frame time over last N frames
|
||||
int fps = 0; // Frames per second
|
||||
int drawCalls = 0; // Draw calls per frame
|
||||
int uiElements = 0; // Number of UI elements rendered
|
||||
int visibleElements = 0; // Number of visible elements
|
||||
|
||||
// Detailed timing breakdowns (added for profiling system)
|
||||
float gridRenderTime = 0.0f; // Time spent rendering grids (ms)
|
||||
float entityRenderTime = 0.0f; // Time spent rendering entities (ms)
|
||||
float fovOverlayTime = 0.0f; // Time spent rendering FOV overlays (ms)
|
||||
float pythonScriptTime = 0.0f; // Time spent in Python callbacks (ms)
|
||||
float animationTime = 0.0f; // Time spent updating animations (ms)
|
||||
|
||||
// Grid-specific metrics
|
||||
int gridCellsRendered = 0; // Number of grid cells drawn this frame
|
||||
int entitiesRendered = 0; // Number of entities drawn this frame
|
||||
int totalEntities = 0; // Total entities in scene
|
||||
|
||||
// Frame time history for averaging
|
||||
static constexpr int HISTORY_SIZE = 60;
|
||||
float frameTimeHistory[HISTORY_SIZE] = {0};
|
||||
int historyIndex = 0;
|
||||
|
||||
void updateFrameTime(float deltaMs) {
|
||||
frameTime = deltaMs;
|
||||
frameTimeHistory[historyIndex] = deltaMs;
|
||||
historyIndex = (historyIndex + 1) % HISTORY_SIZE;
|
||||
|
||||
// Calculate average
|
||||
float sum = 0.0f;
|
||||
for (int i = 0; i < HISTORY_SIZE; ++i) {
|
||||
sum += frameTimeHistory[i];
|
||||
}
|
||||
avgFrameTime = sum / HISTORY_SIZE;
|
||||
fps = avgFrameTime > 0 ? static_cast<int>(1000.0f / avgFrameTime) : 0;
|
||||
}
|
||||
|
||||
void resetPerFrame() {
|
||||
drawCalls = 0;
|
||||
uiElements = 0;
|
||||
visibleElements = 0;
|
||||
|
||||
// Reset per-frame timing metrics
|
||||
gridRenderTime = 0.0f;
|
||||
entityRenderTime = 0.0f;
|
||||
fovOverlayTime = 0.0f;
|
||||
pythonScriptTime = 0.0f;
|
||||
animationTime = 0.0f;
|
||||
|
||||
// Reset per-frame counters
|
||||
gridCellsRendered = 0;
|
||||
entitiesRendered = 0;
|
||||
totalEntities = 0;
|
||||
}
|
||||
} metrics;
|
||||
// Profiling metrics (struct defined above class)
|
||||
ProfilingMetrics metrics;
|
||||
|
||||
GameEngine();
|
||||
GameEngine(const McRogueFaceConfig& cfg);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue