typedef struct TimeStamp { u64 start; u64 finish; String label; } TimeStamp; typedef struct Timings { TimeStamp total; Array(TimeStamp) sections; u64 freq; } Timings; u64 win32_time_stamp_time_now(void) { LARGE_INTEGER counter; QueryPerformanceCounter(&counter); return counter.QuadPart; } u64 win32_time_stamp__freq(void) { gb_local_persist LARGE_INTEGER win32_perf_count_freq = {0}; if (!win32_perf_count_freq.QuadPart) { QueryPerformanceFrequency(&win32_perf_count_freq); GB_ASSERT(win32_perf_count_freq.QuadPart != 0); } return win32_perf_count_freq.QuadPart; } u64 time_stamp_time_now(void) { #if defined(GB_SYSTEM_WINDOWS) return win32_time_stamp_time_now(); #else #error time_stamp_time_now #endif } u64 time_stamp__freq(void) { #if defined(GB_SYSTEM_WINDOWS) return win32_time_stamp__freq(); #else #error time_stamp__freq #endif } TimeStamp make_time_stamp(String label) { TimeStamp ts = {0}; ts.start = time_stamp_time_now(); ts.label = label; return ts; } void timings_init(Timings *t, String label, isize buffer_size) { array_init_reserve(&t->sections, heap_allocator(), buffer_size); t->total = make_time_stamp(label); t->freq = time_stamp__freq(); } void timings_destroy(Timings *t) { array_free(&t->sections); } void timings__stop_current_section(Timings *t) { if (t->sections.count > 0) { t->sections.e[t->sections.count-1].finish = time_stamp_time_now(); } } void timings_start_section(Timings *t, String label) { timings__stop_current_section(t); array_add(&t->sections, make_time_stamp(label)); } f64 time_stamp_as_ms(TimeStamp ts, u64 freq) { GB_ASSERT_MSG(ts.finish >= ts.start, "time_stamp_as_ms - %.*s", LIT(ts.label)); return 1000.0 * cast(f64)(ts.finish - ts.start) / cast(f64)freq; } void timings_print_all(Timings *t) { char const SPACES[] = " "; isize max_len, i; timings__stop_current_section(t); t->total.finish = time_stamp_time_now(); max_len = t->total.label.len; for_array(i, t->sections) { TimeStamp ts = t->sections.e[i]; max_len = gb_max(max_len, ts.label.len); } GB_ASSERT(max_len <= gb_size_of(SPACES)-1); gb_printf("%.*s%.*s - %.3f ms\n", LIT(t->total.label), cast(int)(max_len-t->total.label.len), SPACES, time_stamp_as_ms(t->total, t->freq)); for_array(i, t->sections) { TimeStamp ts = t->sections.e[i]; gb_printf("%.*s%.*s - %.3f ms\n", LIT(ts.label), cast(int)(max_len-ts.label.len), SPACES, time_stamp_as_ms(ts, t->freq)); } }