Browse Source

Add time.Tick for performance related timings

gingerBill 4 years ago
parent
commit
9e8c46b8de
4 changed files with 78 additions and 0 deletions
  1. 39 0
      core/time/perf.odin
  2. 11 0
      core/time/time.odin
  3. 7 0
      core/time/time_unix.odin
  4. 21 0
      core/time/time_windows.odin

+ 39 - 0
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);
+}

+ 11 - 0
core/time/time.odin

@@ -46,9 +46,20 @@ diff :: proc(start, end: Time) -> Duration {
 	return Duration(d);
 	return Duration(d);
 }
 }
 
 
+since :: proc(start: Time) -> Duration {
+	return diff(start, now());
+}
+
+
 duration_nanoseconds :: proc(d: Duration) -> i64 {
 duration_nanoseconds :: proc(d: Duration) -> i64 {
 	return i64(d);
 	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 {
 duration_seconds :: proc(d: Duration) -> f64 {
 	sec := d / Second;
 	sec := d / Second;
 	nsec := d % Second;
 	nsec := d % Second;

+ 7 - 0
core/time/time_unix.odin

@@ -83,3 +83,10 @@ nanosleep :: proc(nanoseconds: i64) -> int {
 	remaining: TimeSpec; // NOTE(tetra): Do we need to initialize this?
 	remaining: TimeSpec; // NOTE(tetra): Do we need to initialize this?
 	return int(_unix_nanosleep(&requested, &remaining));
 	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};
+}

+ 21 - 0
core/time/time_windows.odin

@@ -14,3 +14,24 @@ now :: proc() -> Time {
 sleep :: proc(d: Duration) {
 sleep :: proc(d: Duration) {
 	win32.Sleep(win32.DWORD(d/Millisecond));
 	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};
+}