diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-09-09 15:24:34 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-09-09 15:26:57 +0200 |
| commit | f16e98b074142e87c62cc2e1ea4c6b59251c6e4f (patch) | |
| tree | c2562783cdb9829d8ac1ec4d0ddd11080ef5cc40 /core | |
| parent | f5d5417af75dba8fa2c631f9c101ba2a43bb38f3 (diff) | |
Add xxhash benchmark.
Diffstat (limited to 'core')
| -rw-r--r-- | core/hash/xxhash/common.odin | 87 | ||||
| -rw-r--r-- | core/time/perf.odin | 57 | ||||
| -rw-r--r-- | core/time/time_windows.odin | 3 |
3 files changed, 145 insertions, 2 deletions
diff --git a/core/hash/xxhash/common.odin b/core/hash/xxhash/common.odin index 93a4230c4..fc86ea54b 100644 --- a/core/hash/xxhash/common.odin +++ b/core/hash/xxhash/common.odin @@ -11,6 +11,10 @@ package xxhash import "core:intrinsics" import "core:runtime" +import "core:time" +import "core:fmt" +import "core:testing" + mem_copy :: runtime.mem_copy /* @@ -75,4 +79,85 @@ XXH64_read64 :: #force_inline proc(buf: []u8, alignment: Alignment) -> (res: u64 mem_copy(&b, raw_data(buf[:]), 8) return u64(b) } -}
\ No newline at end of file +} + + +/* + Benchmarks +*/ + +setup_xxhash :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) { + assert(options != nil) + + options.input = make([]u8, options.bytes, allocator) + return nil if len(options.input) == options.bytes else .Allocation_Error +} + +teardown_xxhash :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) { + assert(options != nil) + + delete(options.input) + return nil +} + +benchmark_xxhash32 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) { + buf := options.input + + for _ in 0..=options.rounds { + _ = XXH32(buf) + } + options.count = options.rounds + options.processed = options.rounds * options.bytes + return nil +} + +benchmark_xxhash64 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) { + buf := options.input + + for _ in 0..=options.rounds { + _ = XXH64(buf) + } + options.count = options.rounds + options.processed = options.rounds * options.bytes + return nil +} + +benchmark_print :: proc(name: string, options: ^time.Benchmark_Options) { + fmt.printf("\t[%v] %v rounds, %v bytes procesed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s\n", + name, + options.rounds, + options.processed, + time.duration_nanoseconds(options.duration), + options.rounds_per_second, + options.megabytes_per_second, + ) +} + +@test +benchmark_runner :: proc(t: ^testing.T) { + fmt.println("Starting benchmarks:") + + options := &time.Benchmark_Options{ + rounds = 1_000, + bytes = 100, + setup = setup_xxhash, + bench = benchmark_xxhash32, + teardown = teardown_xxhash, + } + err := time.benchmark(options, context.allocator) + benchmark_print("xxhash32 100 bytes", options) + + options.bytes = 1_000_000 + err = time.benchmark(options, context.allocator) + benchmark_print("xxhash32 1_000_000 bytes", options) + + options.bytes = 100 + options.bench = benchmark_xxhash64 + err = time.benchmark(options, context.allocator) + benchmark_print("xxhash64 100 bytes", options) + + options.bytes = 1_000_000 + err = time.benchmark(options, context.allocator) + benchmark_print("xxhash64 1_000_000 bytes", options) +} + diff --git a/core/time/perf.odin b/core/time/perf.odin index 5146ad543..fcc626d57 100644 --- a/core/time/perf.odin +++ b/core/time/perf.odin @@ -1,5 +1,7 @@ package time +import "core:mem" + Tick :: struct { _nsec: i64, // relative amount } @@ -37,3 +39,58 @@ SCOPED_TICK_DURATION :: proc(d: ^Duration) -> Tick { _tick_duration_end :: proc(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, + + /* + 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 +}
\ No newline at end of file diff --git a/core/time/time_windows.odin b/core/time/time_windows.odin index 18a8c4046..6d4648b12 100644 --- a/core/time/time_windows.odin +++ b/core/time/time_windows.odin @@ -24,7 +24,8 @@ _tick_now :: proc() -> Tick { return q * num + r * num / den } - @thread_local qpc_frequency: win32.LARGE_INTEGER + // @thread_local qpc_frequency: win32.LARGE_INTEGER + qpc_frequency: win32.LARGE_INTEGER if qpc_frequency == 0 { win32.QueryPerformanceFrequency(&qpc_frequency) |