// Lightweight zone-based profiler for measuring the DOD refactor. // Enabled at runtime via KOBO_PROF=1 in the environment. // See plans: .claude/plans/can-you-explain-the-noble-wilkes.md (Phase 0). #ifndef KOBO_PROF_H #define KOBO_PROF_H #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define PROF_MAX_ZONES 32 #define PROF_DUMP_EVERY_FRAMES 600 typedef struct { const char *name; uint64_t calls; uint64_t total_ns; } prof_zone_t; extern prof_zone_t prof_zones[PROF_MAX_ZONES]; extern int prof_nzones; extern int prof_enabled; extern uint64_t prof_frame_count; static inline uint64_t prof_now_ns(void) { #if defined(__APPLE__) || defined(__linux__) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (uint64_t)ts.tv_sec * 1000000000ull + (uint64_t)ts.tv_nsec; #else return 0; #endif } // Returns the index of the zone with the given name, creating it on first use. // Names must be string literals (we compare by pointer for speed). static inline int prof_zone_id(const char *name) { for (int i = 0; i < prof_nzones; ++i) if (prof_zones[i].name == name) return i; if (prof_nzones >= PROF_MAX_ZONES) return PROF_MAX_ZONES - 1; int id = prof_nzones++; prof_zones[id].name = name; prof_zones[id].calls = 0; prof_zones[id].total_ns = 0; return id; } static inline void prof_accumulate(int id, uint64_t ns) { prof_zones[id].calls += 1; prof_zones[id].total_ns += ns; } void prof_init(void); void prof_frame_tick(void); void prof_dump(FILE *f); #ifdef __cplusplus } // RAII helper for C++ scoping. struct ProfScope { int id; uint64_t t0; inline ProfScope(int zone_id) : id(zone_id), t0(prof_enabled ? prof_now_ns() : 0) {} inline ~ProfScope() { if (prof_enabled) prof_accumulate(id, prof_now_ns() - t0); } }; // Pastes the line number to make the static unique per use-site. #define PROF_ZONE_CONCAT2(a,b) a##b #define PROF_ZONE_CONCAT(a,b) PROF_ZONE_CONCAT2(a,b) #define PROF_ZONE(name) \ static int PROF_ZONE_CONCAT(_prof_zid_, __LINE__) = -1; \ if (PROF_ZONE_CONCAT(_prof_zid_, __LINE__) < 0) \ PROF_ZONE_CONCAT(_prof_zid_, __LINE__) = prof_zone_id(name); \ ProfScope PROF_ZONE_CONCAT(_prof_scope_, __LINE__)( \ PROF_ZONE_CONCAT(_prof_zid_, __LINE__)) #endif #endif // KOBO_PROF_H