perf.odin 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package time
  2. import "core:mem"
  3. Tick :: struct {
  4. _nsec: i64, // relative amount
  5. }
  6. tick_now :: proc "contextless" () -> Tick {
  7. return _tick_now()
  8. }
  9. tick_diff :: proc "contextless" (start, end: Tick) -> Duration {
  10. d := end._nsec - start._nsec
  11. return Duration(d)
  12. }
  13. tick_lap_time :: proc "contextless" (prev: ^Tick) -> Duration {
  14. d: Duration
  15. t := tick_now()
  16. if prev._nsec != 0 {
  17. d = tick_diff(prev^, t)
  18. }
  19. prev^ = t
  20. return d
  21. }
  22. tick_since :: proc "contextless" (start: Tick) -> Duration {
  23. return tick_diff(start, tick_now())
  24. }
  25. @(deferred_in_out=_tick_duration_end)
  26. SCOPED_TICK_DURATION :: proc "contextless" (d: ^Duration) -> Tick {
  27. return tick_now()
  28. }
  29. _tick_duration_end :: proc "contextless" (d: ^Duration, t: Tick) {
  30. d^ = tick_since(t)
  31. }
  32. /*
  33. Benchmark helpers
  34. */
  35. Benchmark_Error :: enum {
  36. Okay = 0,
  37. Allocation_Error,
  38. }
  39. Benchmark_Options :: struct {
  40. setup: #type proc(options: ^Benchmark_Options, allocator: mem.Allocator) -> (err: Benchmark_Error),
  41. bench: #type proc(options: ^Benchmark_Options, allocator: mem.Allocator) -> (err: Benchmark_Error),
  42. teardown: #type proc(options: ^Benchmark_Options, allocator: mem.Allocator) -> (err: Benchmark_Error),
  43. rounds: int,
  44. bytes: int,
  45. input: []u8,
  46. count: int,
  47. processed: int,
  48. output: []u8, // Unused for hash benchmarks
  49. hash: u128,
  50. /*
  51. Performance
  52. */
  53. duration: Duration,
  54. rounds_per_second: f64,
  55. megabytes_per_second: f64,
  56. }
  57. benchmark :: proc(options: ^Benchmark_Options, allocator := context.allocator) -> (err: Benchmark_Error) {
  58. assert(options != nil)
  59. assert(options.bench != nil)
  60. if options.setup != nil {
  61. options->setup(allocator) or_return
  62. }
  63. diff: Duration
  64. {
  65. SCOPED_TICK_DURATION(&diff)
  66. options->bench(allocator) or_return
  67. }
  68. options.duration = diff
  69. times_per_second := f64(Second) / f64(diff)
  70. options.rounds_per_second = times_per_second * f64(options.count)
  71. options.megabytes_per_second = f64(options.processed) / f64(1024 * 1024) * times_per_second
  72. if options.teardown != nil {
  73. options->teardown(allocator) or_return
  74. }
  75. return
  76. }