Adds a tiny zone-based profiler (prof.{h,cpp}) enabled via KOBO_PROF=1.
Instruments run_game with zones for myship.move, enemies.move (split into
realize and move_pass), hit_structure, and hit_bolt. Adds KOBO_STRESS=N
to keep the enemy pool topped up with rocks for stable per-frame timing.
Why: the entity/render pipeline refactor in BENCH.md needs a comparable
baseline before any layout changes. Without a stress workload the natural
gameplay enemy count is too noisy to compare across commits.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
42 lines
1.2 KiB
C++
42 lines
1.2 KiB
C++
#include "prof.h"
|
|
|
|
prof_zone_t prof_zones[PROF_MAX_ZONES];
|
|
int prof_nzones = 0;
|
|
int prof_enabled = 0;
|
|
uint64_t prof_frame_count = 0;
|
|
|
|
extern "C" void prof_init(void)
|
|
{
|
|
const char *e = getenv("KOBO_PROF");
|
|
prof_enabled = (e && *e && *e != '0') ? 1 : 0;
|
|
if (prof_enabled)
|
|
fprintf(stderr, "[prof] enabled (dump every %d frames)\n",
|
|
PROF_DUMP_EVERY_FRAMES);
|
|
}
|
|
|
|
extern "C" void prof_dump(FILE *f)
|
|
{
|
|
if (!prof_enabled) return;
|
|
fprintf(f, "[prof] frame=%llu zones=%d\n",
|
|
(unsigned long long)prof_frame_count, prof_nzones);
|
|
for (int i = 0; i < prof_nzones; ++i) {
|
|
prof_zone_t *z = &prof_zones[i];
|
|
double ns_per_call = z->calls ? (double)z->total_ns / (double)z->calls : 0.0;
|
|
double total_ms = (double)z->total_ns / 1.0e6;
|
|
fprintf(f, " %-28s calls=%-10llu total_ms=%-10.3f ns/call=%.1f\n",
|
|
z->name,
|
|
(unsigned long long)z->calls,
|
|
total_ms,
|
|
ns_per_call);
|
|
}
|
|
fflush(f);
|
|
}
|
|
|
|
extern "C" void prof_frame_tick(void)
|
|
{
|
|
if (!prof_enabled) return;
|
|
++prof_frame_count;
|
|
if (prof_frame_count % PROF_DUMP_EVERY_FRAMES == 0)
|
|
prof_dump(stderr);
|
|
}
|