aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2021-09-09 15:24:34 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2021-09-09 15:26:57 +0200
commitf16e98b074142e87c62cc2e1ea4c6b59251c6e4f (patch)
treec2562783cdb9829d8ac1ec4d0ddd11080ef5cc40 /core
parentf5d5417af75dba8fa2c631f9c101ba2a43bb38f3 (diff)
Add xxhash benchmark.
Diffstat (limited to 'core')
-rw-r--r--core/hash/xxhash/common.odin87
-rw-r--r--core/time/perf.odin57
-rw-r--r--core/time/time_windows.odin3
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)