#import "Hash_Table"; #import "Math"; // Each file supplies TIMING_SUPPORTED, timing_read_ticks, and timing_read_tick_frequency_hz. #if OS == .MACOS { #load "timing_macos.jai"; } else #if CPU == .X64 { #load "timing_x64.jai"; } else #if CPU == .ARM64 { #load "timing_arm64.jai"; } else { #assert false "timing.jai: no timing implementation for this CPU."; } TIMING_ACTIVE :: ENABLE_TIMING && TIMING_SUPPORTED; FF :: (val: float64, width:=3) -> FormatFloat #expand { return formatFloat(val, trailing_width = width, zero_removal=.NO); } // Hz, not MHz: QueryPerformanceFrequency can be a fractional number of MHz (19.2 on some ARM64). TICK_FREQUENCY_HZ: u64; timing_set_tick_frequency :: () { #if TIMING_ACTIVE { TICK_FREQUENCY_HZ = timing_read_tick_frequency_hz(); if (TICK_FREQUENCY_HZ == 0) { // On x64: no usable frequency leaf (AMD, pre-Skylake Intel), or a hypervisor reports 0 in them. log("[timing] Tick frequency not detected, set to 3000 MHz\n"); TICK_FREQUENCY_HZ = 3_000_000_000; } else log("[timing] Tick frequency set to % MHz\n", FF(cast(float64) TICK_FREQUENCY_HZ / 1_000_000, 3)); } } Timed_Block_Print :: (block_name:="") #expand { #if TIMING_ACTIVE { if TICK_FREQUENCY_HZ == 0 { log("[Timed_Block_Print] TICK_FREQUENCY_HZ not set (see: timing_set_tick_frequency)!\n"); return; } start_tick := timing_read_ticks(); `defer { elapsed_ticks := timing_read_ticks() - start_tick; elapsed_ticks_f64 := cast(float64)elapsed_ticks; elapsed_time_seconds := elapsed_ticks_f64 / cast(float64) TICK_FREQUENCY_HZ; block_name_print := ifx block_name != "" then block_name else #procedure_name(); log("[%1]: %2 (% ticks)\n", block_name_print, format_time_seconds(elapsed_time_seconds), format_cycles(elapsed_ticks)); } } } // time_code :: (my_code: Code) #expand { // #if ENABLE_TIMING { // start_time := GetUnixTimestamp(); // #insert my_code; // elapsed_time := GetUnixTimestamp() - start_time; // print("[time_code snippet]: %1\n", format_time_seconds(elapsed_time)); // } // } // timing_data: Table(string, u64); // Initialize_Timing_Table :: () { // #if ENABLE_TIMING { // init(*timing_data, 512); // init(*timing_data_unix, 512); // timing_data.allocator = context.default_allocator; // timing_data_unix.allocator = context.default_allocator; // } // }