diff --git a/core/time/perf.odin b/core/time/perf.odin new file mode 100644 index 000000000..f370bedbf --- /dev/null +++ b/core/time/perf.odin @@ -0,0 +1,39 @@ +package time + +Tick :: struct { + _nsec: i64, // relative amount +} + +tick_now :: proc() -> Tick { + return _tick_now(); +} + +tick_diff :: proc(start, end: Tick) -> Duration { + d := end._nsec - start._nsec; + return Duration(d); +} + +tick_lap_time :: proc(prev: ^Tick) -> Duration { + d: Duration; + t := tick_now(); + if prev._nsec != 0 { + d = tick_diff(prev^, t); + } + prev^ = t; + return d; +} + +tick_since :: proc(start: Tick) -> Duration { + return tick_diff(start, tick_now()); +} + + +@(deferred_in_out=_tick_duration_end) +SCOPED_TICK_DURATION :: proc(d: ^Duration) -> Tick { + return tick_now(); +} + + +_tick_duration_end :: proc(d: ^Duration, t: Tick) { + d^ = tick_since(t); +} diff --git a/core/time/time.odin b/core/time/time.odin index f1748998b..6eb4d7cb2 100644 --- a/core/time/time.odin +++ b/core/time/time.odin @@ -46,9 +46,20 @@ diff :: proc(start, end: Time) -> Duration { return Duration(d); } +since :: proc(start: Time) -> Duration { + return diff(start, now()); +} + + duration_nanoseconds :: proc(d: Duration) -> i64 { return i64(d); } +duration_microseconds :: proc(d: Duration) -> f64 { + return duration_seconds(d) * 1e6; +} +duration_milliseconds :: proc(d: Duration) -> f64 { + return duration_seconds(d) * 1e3; +} duration_seconds :: proc(d: Duration) -> f64 { sec := d / Second; nsec := d % Second; diff --git a/core/time/time_unix.odin b/core/time/time_unix.odin index 2419a3f8b..cc9699209 100644 --- a/core/time/time_unix.odin +++ b/core/time/time_unix.odin @@ -83,3 +83,10 @@ nanosleep :: proc(nanoseconds: i64) -> int { remaining: TimeSpec; // NOTE(tetra): Do we need to initialize this? return int(_unix_nanosleep(&requested, &remaining)); } + + +_tick_now :: proc() -> Tick { + t := clock_gettime(CLOCK_MONOTONIC_RAW); + _nsec := t.tv_sec*1e9 + t.tv_nsec; + return Tick{_nsec = _nsec}; +} diff --git a/core/time/time_windows.odin b/core/time/time_windows.odin index 4822d3366..c521ef5be 100644 --- a/core/time/time_windows.odin +++ b/core/time/time_windows.odin @@ -14,3 +14,24 @@ now :: proc() -> Time { sleep :: proc(d: Duration) { win32.Sleep(win32.DWORD(d/Millisecond)); } + + + +_tick_now :: proc() -> Tick { + mul_div_u64 :: proc(val, num, den: i64) -> i64 { + q := val / den; + r := val % den; + return q * num + r * num / den; + } + + @thread_local qpc_frequency: win32.LARGE_INTEGER; + + if qpc_frequency == 0 { + win32.QueryPerformanceFrequency(&qpc_frequency); + } + now: win32.LARGE_INTEGER; + win32.QueryPerformanceCounter(&now); + + _nsec := i64(mul_div_u64(i64(now), 1e9, i64(qpc_frequency))); + return Tick{_nsec = _nsec}; +}