Add xxhash tests to CI.

This commit is contained in:
Jeroen van Rijn
2021-09-09 16:01:44 +02:00
parent f16e98b074
commit 637685316d
5 changed files with 143 additions and 84 deletions

View File

@@ -79,85 +79,4 @@ XXH64_read64 :: #force_inline proc(buf: []u8, alignment: Alignment) -> (res: u64
mem_copy(&b, raw_data(buf[:]), 8)
return u64(b)
}
}
/*
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)
}
}

View File

@@ -60,7 +60,8 @@ Benchmark_Options :: struct {
count: int,
processed: int,
output: []u8,
output: []u8, // Unused for hash benchmarks
hash: u128,
/*
Performance

View File

@@ -1,7 +1,7 @@
ODIN=../../odin
PYTHON=$(shell which python3)
all: download_test_assets image_test compress_test strings_test
all: download_test_assets image_test compress_test strings_test hash_test
download_test_assets:
$(PYTHON) download_assets.py
@@ -14,3 +14,6 @@ compress_test:
strings_test:
$(ODIN) run strings/test_core_strings.odin
hash_test:
$(ODIN) run hash/test_core_hash.odin -o:size -no-bounds-check

View File

@@ -16,3 +16,8 @@ echo ---
echo Running core:strings tests
echo ---
%PATH_TO_ODIN% run strings %COMMON%
echo ---
echo Running core:hash tests
echo ---
%PATH_TO_ODIN% run hash %COMMON% -o:size

View File

@@ -0,0 +1,131 @@
package test_core_image
import "core:hash/xxhash"
import "core:time"
import "core:testing"
import "core:fmt"
TEST_count := 0
TEST_fail := 0
when ODIN_TEST {
expect :: testing.expect
log :: testing.log
} else {
expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) {
fmt.printf("[%v] ", loc)
TEST_count += 1
if !condition {
TEST_fail += 1
fmt.println(" FAIL:", message)
return
}
fmt.println(" PASS")
}
log :: proc(t: ^testing.T, v: any, loc := #caller_location) {
fmt.printf("[%v] ", loc)
fmt.printf("log: %v\n", v)
}
}
main :: proc() {
t := testing.T{}
test_benchmark_runner(&t)
fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
}
/*
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
h: u32
for _ in 0..=options.rounds {
h = xxhash.XXH32(buf)
}
options.count = options.rounds
options.processed = options.rounds * options.bytes
options.hash = u128(h)
return nil
}
benchmark_xxhash64 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
buf := options.input
h: u64
for _ in 0..=options.rounds {
h = xxhash.XXH64(buf)
}
options.count = options.rounds
options.processed = options.rounds * options.bytes
options.hash = u128(h)
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
test_benchmark_runner :: proc(t: ^testing.T) {
fmt.println("Starting benchmarks:")
name := "xxhash32 100 zero bytes"
options := &time.Benchmark_Options{
rounds = 1_000,
bytes = 100,
setup = setup_xxhash,
bench = benchmark_xxhash32,
teardown = teardown_xxhash,
}
err := time.benchmark(options, context.allocator)
expect(t, err == nil, name)
expect(t, options.hash == 0x85f6413c, name)
benchmark_print(name, options)
name = "xxhash32 1 MiB zero bytes"
options.bytes = 1_048_576
err = time.benchmark(options, context.allocator)
expect(t, err == nil, name)
expect(t, options.hash == 0x9430f97f, name)
benchmark_print(name, options)
name = "xxhash64 100 zero bytes"
options.bytes = 100
options.bench = benchmark_xxhash64
err = time.benchmark(options, context.allocator)
expect(t, err == nil, name)
expect(t, options.hash == 0x17bb1103c92c502f, name)
benchmark_print(name, options)
name = "xxhash64 1 MiB zero bytes"
options.bytes = 1_048_576
err = time.benchmark(options, context.allocator)
expect(t, err == nil, name)
expect(t, options.hash == 0x87d2a1b6e1163ef1, name)
benchmark_print(name, options)
}