mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 16:18:52 +00:00
Factor benchmarks out into tests\benchmark\<pkg>
This commit is contained in:
@@ -34,6 +34,7 @@ jobs:
|
|||||||
(cd tests/core; gmake all_bsd)
|
(cd tests/core; gmake all_bsd)
|
||||||
(cd tests/internal; gmake all_bsd)
|
(cd tests/internal; gmake all_bsd)
|
||||||
(cd tests/issues; ./run.sh)
|
(cd tests/issues; ./run.sh)
|
||||||
|
(cd tests/benchmark; gmake all)
|
||||||
build_linux:
|
build_linux:
|
||||||
name: Ubuntu Build, Check, and Test
|
name: Ubuntu Build, Check, and Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -80,6 +81,11 @@ jobs:
|
|||||||
cd tests/internal
|
cd tests/internal
|
||||||
make
|
make
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
- name: Odin core library benchmarks
|
||||||
|
run: |
|
||||||
|
cd tests/benchmark
|
||||||
|
make
|
||||||
|
timeout-minutes: 10
|
||||||
- name: Odin check examples/all for Linux i386
|
- name: Odin check examples/all for Linux i386
|
||||||
run: ./odin check examples/all -vet -strict-style -target:linux_i386
|
run: ./odin check examples/all -vet -strict-style -target:linux_i386
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
@@ -131,6 +137,11 @@ jobs:
|
|||||||
cd tests/internal
|
cd tests/internal
|
||||||
make
|
make
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
- name: Odin core library benchmarks
|
||||||
|
run: |
|
||||||
|
cd tests/benchmark
|
||||||
|
make
|
||||||
|
timeout-minutes: 10
|
||||||
build_macOS_arm:
|
build_macOS_arm:
|
||||||
name: MacOS ARM Build, Check, and Test
|
name: MacOS ARM Build, Check, and Test
|
||||||
runs-on: macos-14 # This is an arm/m1 runner.
|
runs-on: macos-14 # This is an arm/m1 runner.
|
||||||
@@ -170,6 +181,11 @@ jobs:
|
|||||||
cd tests/internal
|
cd tests/internal
|
||||||
make
|
make
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
- name: Odin core library benchmarks
|
||||||
|
run: |
|
||||||
|
cd tests/benchmark
|
||||||
|
make
|
||||||
|
timeout-minutes: 10
|
||||||
build_windows:
|
build_windows:
|
||||||
name: Windows Build, Check, and Test
|
name: Windows Build, Check, and Test
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
@@ -245,6 +261,13 @@ jobs:
|
|||||||
cd tests\core\math\big
|
cd tests\core\math\big
|
||||||
call build.bat
|
call build.bat
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
- name: core library benchmarks
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
|
cd tests\benchmark
|
||||||
|
call build.bat
|
||||||
|
timeout-minutes: 10
|
||||||
- name: Odin check examples/all for Windows 32bits
|
- name: Odin check examples/all for Windows 32bits
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
ODIN=../../odin
|
||||||
|
COMMON=-no-bounds-check -vet -strict-style
|
||||||
|
|
||||||
|
all: crypto_bench \
|
||||||
|
hash_bench
|
||||||
|
|
||||||
|
crypto_bench:
|
||||||
|
$(ODIN) test crypto $(COMMON) -o:speed -out:bench_crypto
|
||||||
|
|
||||||
|
hash_bench:
|
||||||
|
$(ODIN) test hash $(COMMON) -o:speed -out:bench_hash
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm bench_*
|
||||||
@@ -0,0 +1,356 @@
|
|||||||
|
package benchmark_core_crypto
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:encoding/hex"
|
||||||
|
import "core:fmt"
|
||||||
|
import "core:log"
|
||||||
|
import "core:strings"
|
||||||
|
import "core:testing"
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
|
import "core:crypto/aes"
|
||||||
|
import "core:crypto/chacha20"
|
||||||
|
import "core:crypto/chacha20poly1305"
|
||||||
|
import "core:crypto/ed25519"
|
||||||
|
import "core:crypto/poly1305"
|
||||||
|
import "core:crypto/x25519"
|
||||||
|
|
||||||
|
// Cryptographic primitive benchmarks.
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
benchmark_crypto :: proc(t: ^testing.T) {
|
||||||
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
|
str: strings.Builder
|
||||||
|
strings.builder_init(&str, context.allocator)
|
||||||
|
defer {
|
||||||
|
log.info(strings.to_string(str))
|
||||||
|
strings.builder_destroy(&str)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
name := "ChaCha20 64 bytes"
|
||||||
|
options := &time.Benchmark_Options {
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 64,
|
||||||
|
setup = _setup_sized_buf,
|
||||||
|
bench = _benchmark_chacha20,
|
||||||
|
teardown = _teardown_sized_buf,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
|
||||||
|
name = "ChaCha20 1024 bytes"
|
||||||
|
options.bytes = 1024
|
||||||
|
err = time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
|
||||||
|
name = "ChaCha20 65536 bytes"
|
||||||
|
options.bytes = 65536
|
||||||
|
err = time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name := "Poly1305 64 zero bytes"
|
||||||
|
options := &time.Benchmark_Options {
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 64,
|
||||||
|
setup = _setup_sized_buf,
|
||||||
|
bench = _benchmark_poly1305,
|
||||||
|
teardown = _teardown_sized_buf,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
|
||||||
|
name = "Poly1305 1024 zero bytes"
|
||||||
|
options.bytes = 1024
|
||||||
|
err = time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name := "chacha20poly1305 64 bytes"
|
||||||
|
options := &time.Benchmark_Options {
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 64,
|
||||||
|
setup = _setup_sized_buf,
|
||||||
|
bench = _benchmark_chacha20poly1305,
|
||||||
|
teardown = _teardown_sized_buf,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
|
||||||
|
name = "chacha20poly1305 1024 bytes"
|
||||||
|
options.bytes = 1024
|
||||||
|
err = time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
|
||||||
|
name = "chacha20poly1305 65536 bytes"
|
||||||
|
options.bytes = 65536
|
||||||
|
err = time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name := "AES256-GCM 64 bytes"
|
||||||
|
options := &time.Benchmark_Options {
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 64,
|
||||||
|
setup = _setup_sized_buf,
|
||||||
|
bench = _benchmark_aes256_gcm,
|
||||||
|
teardown = _teardown_sized_buf,
|
||||||
|
}
|
||||||
|
|
||||||
|
key := [aes.KEY_SIZE_256]byte {
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
}
|
||||||
|
ctx: aes.Context_GCM
|
||||||
|
aes.init_gcm(&ctx, key[:])
|
||||||
|
|
||||||
|
context.user_ptr = &ctx
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
|
||||||
|
name = "AES256-GCM 1024 bytes"
|
||||||
|
options.bytes = 1024
|
||||||
|
err = time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
|
||||||
|
name = "AES256-GCM 65536 bytes"
|
||||||
|
options.bytes = 65536
|
||||||
|
err = time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil, name)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
iters :: 10000
|
||||||
|
|
||||||
|
priv_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
|
||||||
|
priv_bytes, _ := hex.decode(transmute([]byte)(priv_str), context.temp_allocator)
|
||||||
|
priv_key: ed25519.Private_Key
|
||||||
|
start := time.now()
|
||||||
|
for i := 0; i < iters; i = i + 1 {
|
||||||
|
ok := ed25519.private_key_set_bytes(&priv_key, priv_bytes)
|
||||||
|
assert(ok, "private key should deserialize")
|
||||||
|
}
|
||||||
|
elapsed := time.since(start)
|
||||||
|
fmt.sbprintfln(&str,
|
||||||
|
"ed25519.private_key_set_bytes: ~%f us/op",
|
||||||
|
time.duration_microseconds(elapsed) / iters,
|
||||||
|
)
|
||||||
|
|
||||||
|
pub_bytes := priv_key._pub_key._b[:] // "I know what I am doing"
|
||||||
|
pub_key: ed25519.Public_Key
|
||||||
|
start = time.now()
|
||||||
|
for i := 0; i < iters; i = i + 1 {
|
||||||
|
ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes[:])
|
||||||
|
assert(ok, "public key should deserialize")
|
||||||
|
}
|
||||||
|
elapsed = time.since(start)
|
||||||
|
fmt.sbprintfln(&str,
|
||||||
|
"ed25519.public_key_set_bytes: ~%f us/op",
|
||||||
|
time.duration_microseconds(elapsed) / iters,
|
||||||
|
)
|
||||||
|
|
||||||
|
msg := "Got a job for you, 621."
|
||||||
|
sig_bytes: [ed25519.SIGNATURE_SIZE]byte
|
||||||
|
msg_bytes := transmute([]byte)(msg)
|
||||||
|
start = time.now()
|
||||||
|
for i := 0; i < iters; i = i + 1 {
|
||||||
|
ed25519.sign(&priv_key, msg_bytes, sig_bytes[:])
|
||||||
|
}
|
||||||
|
elapsed = time.since(start)
|
||||||
|
fmt.sbprintfln(&str,
|
||||||
|
"ed25519.sign: ~%f us/op",
|
||||||
|
time.duration_microseconds(elapsed) / iters,
|
||||||
|
)
|
||||||
|
|
||||||
|
start = time.now()
|
||||||
|
for i := 0; i < iters; i = i + 1 {
|
||||||
|
ok := ed25519.verify(&pub_key, msg_bytes, sig_bytes[:])
|
||||||
|
assert(ok, "signature should validate")
|
||||||
|
}
|
||||||
|
elapsed = time.since(start)
|
||||||
|
fmt.sbprintfln(&str,
|
||||||
|
"ed25519.verify: ~%f us/op",
|
||||||
|
time.duration_microseconds(elapsed) / iters,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||||
|
scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
|
||||||
|
|
||||||
|
point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator)
|
||||||
|
scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator)
|
||||||
|
out: [x25519.POINT_SIZE]byte = ---
|
||||||
|
|
||||||
|
iters :: 10000
|
||||||
|
start := time.now()
|
||||||
|
for i := 0; i < iters; i = i + 1 {
|
||||||
|
x25519.scalarmult(out[:], scalar[:], point[:])
|
||||||
|
}
|
||||||
|
elapsed := time.since(start)
|
||||||
|
|
||||||
|
fmt.sbprintfln(&str,
|
||||||
|
"x25519.scalarmult: ~%f us/op",
|
||||||
|
time.duration_microseconds(elapsed) / iters,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
_setup_sized_buf :: 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
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
_teardown_sized_buf :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
assert(options != nil)
|
||||||
|
|
||||||
|
delete(options.input)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
_benchmark_chacha20 :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
buf := options.input
|
||||||
|
key := [chacha20.KEY_SIZE]byte {
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
}
|
||||||
|
nonce := [chacha20.NONCE_SIZE]byte {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx: chacha20.Context = ---
|
||||||
|
chacha20.init(&ctx, key[:], nonce[:])
|
||||||
|
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
chacha20.xor_bytes(&ctx, buf, buf)
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
_benchmark_poly1305 :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
buf := options.input
|
||||||
|
key := [poly1305.KEY_SIZE]byte {
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
}
|
||||||
|
|
||||||
|
tag: [poly1305.TAG_SIZE]byte = ---
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
poly1305.sum(tag[:], buf, key[:])
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
//options.hash = u128(h)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
_benchmark_chacha20poly1305 :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
buf := options.input
|
||||||
|
key := [chacha20.KEY_SIZE]byte {
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
}
|
||||||
|
nonce := [chacha20.NONCE_SIZE]byte {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
}
|
||||||
|
|
||||||
|
tag: [chacha20poly1305.TAG_SIZE]byte = ---
|
||||||
|
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
chacha20poly1305.encrypt(buf, tag[:], key[:], nonce[:], nil, buf)
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_benchmark_aes256_gcm :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
buf := options.input
|
||||||
|
nonce: [aes.GCM_NONCE_SIZE]byte
|
||||||
|
tag: [aes.GCM_TAG_SIZE]byte = ---
|
||||||
|
|
||||||
|
ctx := transmute(^aes.Context_GCM)context.user_ptr
|
||||||
|
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
aes.seal_gcm(ctx, buf, tag[:], nonce[:], nil, buf)
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
benchmark_print :: proc(str: ^strings.Builder, name: string, options: ^time.Benchmark_Options, loc := #caller_location) {
|
||||||
|
fmt.sbprintfln(str, "[%v] %v rounds, %v bytes processed 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,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
package benchmark_core_hash
|
||||||
|
|
||||||
|
import "core:fmt"
|
||||||
|
import "core:hash/xxhash"
|
||||||
|
import "base:intrinsics"
|
||||||
|
import "core:strings"
|
||||||
|
import "core:testing"
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
benchmark_hash :: proc(t: ^testing.T) {
|
||||||
|
str: strings.Builder
|
||||||
|
strings.builder_init(&str, context.allocator)
|
||||||
|
defer {
|
||||||
|
fmt.println(strings.to_string(str))
|
||||||
|
strings.builder_destroy(&str)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
name := "XXH32 100 zero bytes"
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 100,
|
||||||
|
setup = setup_xxhash,
|
||||||
|
bench = benchmark_xxh32,
|
||||||
|
teardown = teardown_xxhash,
|
||||||
|
}
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
||||||
|
hash := u128(0x85f6413c)
|
||||||
|
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name := "XXH32 1 MiB zero bytes"
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 1_048_576,
|
||||||
|
setup = setup_xxhash,
|
||||||
|
bench = benchmark_xxh32,
|
||||||
|
teardown = teardown_xxhash,
|
||||||
|
}
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
||||||
|
hash := u128(0x9430f97f)
|
||||||
|
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name := "XXH64 100 zero bytes"
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 100,
|
||||||
|
setup = setup_xxhash,
|
||||||
|
bench = benchmark_xxh64,
|
||||||
|
teardown = teardown_xxhash,
|
||||||
|
}
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
||||||
|
hash := u128(0x17bb1103c92c502f)
|
||||||
|
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name := "XXH64 1 MiB zero bytes"
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 1_048_576,
|
||||||
|
setup = setup_xxhash,
|
||||||
|
bench = benchmark_xxh64,
|
||||||
|
teardown = teardown_xxhash,
|
||||||
|
}
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
||||||
|
hash := u128(0x87d2a1b6e1163ef1)
|
||||||
|
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name := "XXH3_64 100 zero bytes"
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 100,
|
||||||
|
setup = setup_xxhash,
|
||||||
|
bench = benchmark_xxh3_64,
|
||||||
|
teardown = teardown_xxhash,
|
||||||
|
}
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
||||||
|
hash := u128(0x801fedc74ccd608c)
|
||||||
|
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name := "XXH3_64 1 MiB zero bytes"
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 1_048_576,
|
||||||
|
setup = setup_xxhash,
|
||||||
|
bench = benchmark_xxh3_64,
|
||||||
|
teardown = teardown_xxhash,
|
||||||
|
}
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
||||||
|
hash := u128(0x918780b90550bf34)
|
||||||
|
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name := "XXH3_128 100 zero bytes"
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 100,
|
||||||
|
setup = setup_xxhash,
|
||||||
|
bench = benchmark_xxh3_128,
|
||||||
|
teardown = teardown_xxhash,
|
||||||
|
}
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
||||||
|
hash := u128(0x6ba30a4e9dffe1ff801fedc74ccd608c)
|
||||||
|
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name := "XXH3_128 1 MiB zero bytes"
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = 1_000,
|
||||||
|
bytes = 1_048_576,
|
||||||
|
setup = setup_xxhash,
|
||||||
|
bench = benchmark_xxh3_128,
|
||||||
|
teardown = teardown_xxhash,
|
||||||
|
}
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
||||||
|
hash := u128(0xb6ef17a3448492b6918780b90550bf34)
|
||||||
|
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
||||||
|
benchmark_print(&str, name, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_xxh32 :: 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_xxh64 :: 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_xxh3_64 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
|
||||||
|
buf := options.input
|
||||||
|
|
||||||
|
h: u64
|
||||||
|
for _ in 0..=options.rounds {
|
||||||
|
h = xxhash.XXH3_64(buf)
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
options.hash = u128(h)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmark_xxh3_128 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
|
||||||
|
buf := options.input
|
||||||
|
|
||||||
|
h: u128
|
||||||
|
for _ in 0..=options.rounds {
|
||||||
|
h = xxhash.XXH3_128(buf)
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
options.hash = h
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmark_print :: proc(str: ^strings.Builder, name: string, options: ^time.Benchmark_Options, loc := #caller_location) {
|
||||||
|
fmt.sbprintfln(str, "[%v] %v rounds, %v bytes processed 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,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,353 +0,0 @@
|
|||||||
package test_core_crypto
|
|
||||||
|
|
||||||
import "base:runtime"
|
|
||||||
import "core:encoding/hex"
|
|
||||||
import "core:log"
|
|
||||||
import "core:testing"
|
|
||||||
import "core:time"
|
|
||||||
|
|
||||||
import "core:crypto/aes"
|
|
||||||
import "core:crypto/chacha20"
|
|
||||||
import "core:crypto/chacha20poly1305"
|
|
||||||
import "core:crypto/ed25519"
|
|
||||||
import "core:crypto/poly1305"
|
|
||||||
import "core:crypto/x25519"
|
|
||||||
|
|
||||||
// Cryptographic primitive benchmarks.
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
bench_crypto :: proc(t: ^testing.T) {
|
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
||||||
bench_chacha20(t)
|
|
||||||
bench_poly1305(t)
|
|
||||||
bench_chacha20poly1305(t)
|
|
||||||
bench_aes256_gcm(t)
|
|
||||||
bench_ed25519(t)
|
|
||||||
bench_x25519(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
_setup_sized_buf :: 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_sized_buf :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
assert(options != nil)
|
|
||||||
|
|
||||||
delete(options.input)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_benchmark_chacha20 :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
key := [chacha20.KEY_SIZE]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
nonce := [chacha20.NONCE_SIZE]byte {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx: chacha20.Context = ---
|
|
||||||
chacha20.init(&ctx, key[:], nonce[:])
|
|
||||||
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
chacha20.xor_bytes(&ctx, buf, buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_benchmark_poly1305 :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
key := [poly1305.KEY_SIZE]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
|
|
||||||
tag: [poly1305.TAG_SIZE]byte = ---
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
poly1305.sum(tag[:], buf, key[:])
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
//options.hash = u128(h)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_benchmark_chacha20poly1305 :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
key := [chacha20.KEY_SIZE]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
nonce := [chacha20.NONCE_SIZE]byte {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
|
|
||||||
tag: [chacha20poly1305.TAG_SIZE]byte = ---
|
|
||||||
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
chacha20poly1305.encrypt(buf, tag[:], key[:], nonce[:], nil, buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_benchmark_aes256_gcm :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
nonce: [aes.GCM_NONCE_SIZE]byte
|
|
||||||
tag: [aes.GCM_TAG_SIZE]byte = ---
|
|
||||||
|
|
||||||
ctx := transmute(^aes.Context_GCM)context.user_ptr
|
|
||||||
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
aes.seal_gcm(ctx, buf, tag[:], nonce[:], nil, buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
benchmark_print :: proc(name: string, options: ^time.Benchmark_Options) {
|
|
||||||
log.infof(
|
|
||||||
"\n\t[%v] %v rounds, %v bytes processed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s",
|
|
||||||
name,
|
|
||||||
options.rounds,
|
|
||||||
options.processed,
|
|
||||||
time.duration_nanoseconds(options.duration),
|
|
||||||
options.rounds_per_second,
|
|
||||||
options.megabytes_per_second,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench_chacha20 :: proc(t: ^testing.T) {
|
|
||||||
name := "ChaCha20 64 bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_chacha20,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
|
|
||||||
name = "ChaCha20 1024 bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
|
|
||||||
name = "ChaCha20 65536 bytes"
|
|
||||||
options.bytes = 65536
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench_poly1305 :: proc(t: ^testing.T) {
|
|
||||||
name := "Poly1305 64 zero bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_poly1305,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
|
|
||||||
name = "Poly1305 1024 zero bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench_chacha20poly1305 :: proc(t: ^testing.T) {
|
|
||||||
name := "chacha20poly1305 64 bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_chacha20poly1305,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
|
|
||||||
name = "chacha20poly1305 1024 bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
|
|
||||||
name = "chacha20poly1305 65536 bytes"
|
|
||||||
options.bytes = 65536
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench_aes256_gcm :: proc(t: ^testing.T) {
|
|
||||||
name := "AES256-GCM 64 bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_aes256_gcm,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
key := [aes.KEY_SIZE_256]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
ctx: aes.Context_GCM
|
|
||||||
aes.init_gcm(&ctx, key[:])
|
|
||||||
|
|
||||||
context.user_ptr = &ctx
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
|
|
||||||
name = "AES256-GCM 1024 bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
|
|
||||||
name = "AES256-GCM 65536 bytes"
|
|
||||||
options.bytes = 65536
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench_ed25519 :: proc(t: ^testing.T) {
|
|
||||||
iters :: 10000
|
|
||||||
|
|
||||||
priv_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
|
|
||||||
priv_bytes, _ := hex.decode(transmute([]byte)(priv_str), context.temp_allocator)
|
|
||||||
priv_key: ed25519.Private_Key
|
|
||||||
start := time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
ok := ed25519.private_key_set_bytes(&priv_key, priv_bytes)
|
|
||||||
assert(ok, "private key should deserialize")
|
|
||||||
}
|
|
||||||
elapsed := time.since(start)
|
|
||||||
log.infof(
|
|
||||||
"ed25519.private_key_set_bytes: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
|
|
||||||
pub_bytes := priv_key._pub_key._b[:] // "I know what I am doing"
|
|
||||||
pub_key: ed25519.Public_Key
|
|
||||||
start = time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes[:])
|
|
||||||
assert(ok, "public key should deserialize")
|
|
||||||
}
|
|
||||||
elapsed = time.since(start)
|
|
||||||
log.infof(
|
|
||||||
"ed25519.public_key_set_bytes: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
|
|
||||||
msg := "Got a job for you, 621."
|
|
||||||
sig_bytes: [ed25519.SIGNATURE_SIZE]byte
|
|
||||||
msg_bytes := transmute([]byte)(msg)
|
|
||||||
start = time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
ed25519.sign(&priv_key, msg_bytes, sig_bytes[:])
|
|
||||||
}
|
|
||||||
elapsed = time.since(start)
|
|
||||||
log.infof(
|
|
||||||
"ed25519.sign: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
|
|
||||||
start = time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
ok := ed25519.verify(&pub_key, msg_bytes, sig_bytes[:])
|
|
||||||
assert(ok, "signature should validate")
|
|
||||||
}
|
|
||||||
elapsed = time.since(start)
|
|
||||||
log.infof(
|
|
||||||
"ed25519.verify: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench_x25519 :: proc(t: ^testing.T) {
|
|
||||||
point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
|
||||||
scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
|
|
||||||
|
|
||||||
point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator)
|
|
||||||
scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator)
|
|
||||||
out: [x25519.POINT_SIZE]byte = ---
|
|
||||||
|
|
||||||
iters :: 10000
|
|
||||||
start := time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
x25519.scalarmult(out[:], scalar[:], point[:])
|
|
||||||
}
|
|
||||||
elapsed := time.since(start)
|
|
||||||
|
|
||||||
log.infof(
|
|
||||||
"x25519.scalarmult: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -2,10 +2,7 @@ package test_core_hash
|
|||||||
|
|
||||||
import "core:hash/xxhash"
|
import "core:hash/xxhash"
|
||||||
import "core:hash"
|
import "core:hash"
|
||||||
import "core:time"
|
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
import "core:fmt"
|
|
||||||
import "core:log"
|
|
||||||
import "core:math/rand"
|
import "core:math/rand"
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
|
|
||||||
@@ -78,15 +75,10 @@ test_xxhash_zero_streamed_random_updates :: proc(t: ^testing.T) {
|
|||||||
xxh3_64 := xxhash.XXH3_64_digest(xxh3_64_state)
|
xxh3_64 := xxhash.XXH3_64_digest(xxh3_64_state)
|
||||||
xxh3_128 := xxhash.XXH3_128_digest(xxh3_128_state)
|
xxh3_128 := xxhash.XXH3_128_digest(xxh3_128_state)
|
||||||
|
|
||||||
xxh32_error := fmt.tprintf("[ XXH32(%03d) ] Expected: %08x, got: %08x", i, v.xxh_32, xxh32)
|
testing.expectf(t, xxh32 == v.xxh_32, "[ XXH32(%03d) ] Expected: %08x, got: %08x", i, v.xxh_32, xxh32)
|
||||||
xxh64_error := fmt.tprintf("[ XXH64(%03d) ] Expected: %16x, got: %16x", i, v.xxh_64, xxh64)
|
testing.expectf(t, xxh64 == v.xxh_64, "[ XXH64(%03d) ] Expected: %16x, got: %16x", i, v.xxh_64, xxh64)
|
||||||
xxh3_64_error := fmt.tprintf("[XXH3_64(%03d) ] Expected: %16x, got: %16x", i, v.xxh3_64, xxh3_64)
|
testing.expectf(t, xxh3_64 == v.xxh3_64, "[XXH3_64(%03d) ] Expected: %16x, got: %16x", i, v.xxh3_64, xxh3_64)
|
||||||
xxh3_128_error := fmt.tprintf("[XXH3_128(%03d) ] Expected: %32x, got: %32x", i, v.xxh3_128, xxh3_128)
|
testing.expectf(t, xxh3_128 == v.xxh3_128, "[XXH3_128(%03d) ] Expected: %32x, got: %32x", i, v.xxh3_128, xxh3_128)
|
||||||
|
|
||||||
testing.expect(t, xxh32 == v.xxh_32, xxh32_error)
|
|
||||||
testing.expect(t, xxh64 == v.xxh_64, xxh64_error)
|
|
||||||
testing.expect(t, xxh3_64 == v.xxh3_64, xxh3_64_error)
|
|
||||||
testing.expect(t, xxh3_128 == v.xxh3_128, xxh3_128_error)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,220 +166,4 @@ test_crc64_vectors :: proc(t: ^testing.T) {
|
|||||||
testing.expectf(t, iso == expected[2], "[ CRC-64 ISO 3306] Expected: %016x, got: %016x", expected[2], iso)
|
testing.expectf(t, iso == expected[2], "[ CRC-64 ISO 3306] Expected: %016x, got: %016x", expected[2], iso)
|
||||||
testing.expectf(t, iso2 == expected[3], "[~CRC-64 ISO 3306] Expected: %016x, got: %016x", expected[3], iso2)
|
testing.expectf(t, iso2 == expected[3], "[~CRC-64 ISO 3306] Expected: %016x, got: %016x", expected[3], iso2)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_benchmark_xxh32 :: proc(t: ^testing.T) {
|
|
||||||
name := "XXH32 100 zero bytes"
|
|
||||||
options := &time.Benchmark_Options{
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 100,
|
|
||||||
setup = setup_xxhash,
|
|
||||||
bench = benchmark_xxh32,
|
|
||||||
teardown = teardown_xxhash,
|
|
||||||
}
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
|
||||||
hash := u128(0x85f6413c)
|
|
||||||
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_benchmark_xxh32_1MB :: proc(t: ^testing.T) {
|
|
||||||
name := "XXH32 1 MiB zero bytes"
|
|
||||||
options := &time.Benchmark_Options{
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 1_048_576,
|
|
||||||
setup = setup_xxhash,
|
|
||||||
bench = benchmark_xxh32,
|
|
||||||
teardown = teardown_xxhash,
|
|
||||||
}
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
|
||||||
hash := u128(0x9430f97f)
|
|
||||||
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_benchmark_xxh64 :: proc(t: ^testing.T) {
|
|
||||||
name := "XXH64 100 zero bytes"
|
|
||||||
options := &time.Benchmark_Options{
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 100,
|
|
||||||
setup = setup_xxhash,
|
|
||||||
bench = benchmark_xxh64,
|
|
||||||
teardown = teardown_xxhash,
|
|
||||||
}
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
|
||||||
hash := u128(0x17bb1103c92c502f)
|
|
||||||
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_benchmark_xxh64_1MB :: proc(t: ^testing.T) {
|
|
||||||
name := "XXH64 1 MiB zero bytes"
|
|
||||||
options := &time.Benchmark_Options{
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 1_048_576,
|
|
||||||
setup = setup_xxhash,
|
|
||||||
bench = benchmark_xxh64,
|
|
||||||
teardown = teardown_xxhash,
|
|
||||||
}
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
|
||||||
hash := u128(0x87d2a1b6e1163ef1)
|
|
||||||
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_benchmark_xxh3_64 :: proc(t: ^testing.T) {
|
|
||||||
name := "XXH3_64 100 zero bytes"
|
|
||||||
options := &time.Benchmark_Options{
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 100,
|
|
||||||
setup = setup_xxhash,
|
|
||||||
bench = benchmark_xxh3_64,
|
|
||||||
teardown = teardown_xxhash,
|
|
||||||
}
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
|
||||||
hash := u128(0x801fedc74ccd608c)
|
|
||||||
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_benchmark_xxh3_64_1MB :: proc(t: ^testing.T) {
|
|
||||||
name := "XXH3_64 1 MiB zero bytes"
|
|
||||||
options := &time.Benchmark_Options{
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 1_048_576,
|
|
||||||
setup = setup_xxhash,
|
|
||||||
bench = benchmark_xxh3_64,
|
|
||||||
teardown = teardown_xxhash,
|
|
||||||
}
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
|
||||||
hash := u128(0x918780b90550bf34)
|
|
||||||
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_benchmark_xxh3_128 :: proc(t: ^testing.T) {
|
|
||||||
name := "XXH3_128 100 zero bytes"
|
|
||||||
options := &time.Benchmark_Options{
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 100,
|
|
||||||
setup = setup_xxhash,
|
|
||||||
bench = benchmark_xxh3_128,
|
|
||||||
teardown = teardown_xxhash,
|
|
||||||
}
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
|
||||||
hash := u128(0x6ba30a4e9dffe1ff801fedc74ccd608c)
|
|
||||||
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_benchmark_xxh3_128_1MB :: proc(t: ^testing.T) {
|
|
||||||
name := "XXH3_128 1 MiB zero bytes"
|
|
||||||
options := &time.Benchmark_Options{
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 1_048_576,
|
|
||||||
setup = setup_xxhash,
|
|
||||||
bench = benchmark_xxh3_128,
|
|
||||||
teardown = teardown_xxhash,
|
|
||||||
}
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expectf(t, err == nil, "%s failed with err %v", name, err)
|
|
||||||
hash := u128(0xb6ef17a3448492b6918780b90550bf34)
|
|
||||||
testing.expectf(t, options.hash == hash, "%v hash expected to be %v, got %v", name, hash, options.hash)
|
|
||||||
benchmark_print(name, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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_xxh32 :: 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_xxh64 :: 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_xxh3_64 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
|
|
||||||
buf := options.input
|
|
||||||
|
|
||||||
h: u64
|
|
||||||
for _ in 0..=options.rounds {
|
|
||||||
h = xxhash.XXH3_64(buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
options.hash = u128(h)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
benchmark_xxh3_128 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
|
|
||||||
buf := options.input
|
|
||||||
|
|
||||||
h: u128
|
|
||||||
for _ in 0..=options.rounds {
|
|
||||||
h = xxhash.XXH3_128(buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
options.hash = h
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
benchmark_print :: proc(name: string, options: ^time.Benchmark_Options, loc := #caller_location) {
|
|
||||||
log.infof("\n\t[%v] %v rounds, %v bytes processed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s",
|
|
||||||
name,
|
|
||||||
options.rounds,
|
|
||||||
options.processed,
|
|
||||||
time.duration_nanoseconds(options.duration),
|
|
||||||
options.rounds_per_second,
|
|
||||||
options.megabytes_per_second,
|
|
||||||
location=loc,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user