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