mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 14:09:13 +00:00
Benchmark libc.
This commit is contained in:
31
sqlite3/libc/build.sh
Executable file
31
sqlite3/libc/build.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd -P -- "$(dirname -- "$0")"
|
||||
|
||||
ROOT=../../
|
||||
BINARYEN="$ROOT/tools/binaryen/bin"
|
||||
WASI_SDK="$ROOT/tools/wasi-sdk/bin"
|
||||
|
||||
trap 'rm -f libc.tmp' EXIT
|
||||
|
||||
"$WASI_SDK/clang" --target=wasm32-wasi -std=c23 -g0 -O2 \
|
||||
-o libc.wasm ../strings.c \
|
||||
-mexec-model=reactor \
|
||||
-msimd128 -mmutable-globals -mmultivalue \
|
||||
-mbulk-memory -mreference-types \
|
||||
-mnontrapping-fptoint -msign-ext \
|
||||
-fno-stack-protector -fno-stack-clash-protection \
|
||||
-Wl,--initial-memory=16777216 \
|
||||
-Wl,--export=memset \
|
||||
-Wl,--export=memcpy \
|
||||
-Wl,--export=memcmp
|
||||
|
||||
"$BINARYEN/wasm-ctor-eval" -g -c _initialize libc.wasm -o libc.tmp
|
||||
"$BINARYEN/wasm-opt" -g --strip --strip-producers -c -O3 \
|
||||
libc.tmp -o libc.wasm \
|
||||
--enable-simd --enable-mutable-globals --enable-multivalue \
|
||||
--enable-bulk-memory --enable-reference-types \
|
||||
--enable-nontrapping-float-to-int --enable-sign-ext
|
||||
|
||||
"$BINARYEN/wasm-dis" -o libc.wat libc.wasm
|
||||
BIN
sqlite3/libc/libc.wasm
Executable file
BIN
sqlite3/libc/libc.wasm
Executable file
Binary file not shown.
137
sqlite3/libc/libc.wat
Normal file
137
sqlite3/libc/libc.wat
Normal file
@@ -0,0 +1,137 @@
|
||||
(module $libc.wasm
|
||||
(type $0 (func (param i32 i32 i32) (result i32)))
|
||||
(memory $0 256)
|
||||
(data $0 (i32.const 1024) "\01")
|
||||
(export "memory" (memory $0))
|
||||
(export "memset" (func $memset))
|
||||
(export "memcpy" (func $memcpy))
|
||||
(export "memcmp" (func $memcmp))
|
||||
(func $memset (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
||||
(memory.fill
|
||||
(local.get $0)
|
||||
(local.get $1)
|
||||
(local.get $2)
|
||||
)
|
||||
(local.get $0)
|
||||
)
|
||||
(func $memcpy (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
||||
(memory.copy
|
||||
(local.get $0)
|
||||
(local.get $1)
|
||||
(local.get $2)
|
||||
)
|
||||
(local.get $0)
|
||||
)
|
||||
(func $memcmp (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
||||
(local $3 i32)
|
||||
(local $4 i32)
|
||||
(block $block2
|
||||
(block $block1
|
||||
(block $block
|
||||
(br_if $block
|
||||
(i32.lt_u
|
||||
(local.get $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(br_if $block
|
||||
(i32.and
|
||||
(i32.or
|
||||
(local.get $0)
|
||||
(local.get $1)
|
||||
)
|
||||
(i32.const 7)
|
||||
)
|
||||
)
|
||||
(loop $label
|
||||
(br_if $block1
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(local.get $0)
|
||||
)
|
||||
(i64.load
|
||||
(local.get $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(local.set $1
|
||||
(i32.add
|
||||
(local.get $1)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(local.set $0
|
||||
(i32.add
|
||||
(local.get $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(br_if $label
|
||||
(i32.gt_u
|
||||
(local.tee $2
|
||||
(i32.sub
|
||||
(local.get $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(i32.const 7)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br_if $block2
|
||||
(i32.eqz
|
||||
(local.get $2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $label1
|
||||
(if
|
||||
(i32.ne
|
||||
(local.tee $3
|
||||
(i32.load8_u
|
||||
(local.get $0)
|
||||
)
|
||||
)
|
||||
(local.tee $4
|
||||
(i32.load8_u
|
||||
(local.get $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(then
|
||||
(return
|
||||
(i32.sub
|
||||
(local.get $3)
|
||||
(local.get $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(local.set $1
|
||||
(i32.add
|
||||
(local.get $1)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(local.set $0
|
||||
(i32.add
|
||||
(local.get $0)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br_if $label1
|
||||
(local.tee $2
|
||||
(i32.sub
|
||||
(local.get $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.const 0)
|
||||
)
|
||||
;; features section: mutable-globals, nontrapping-float-to-int, simd, bulk-memory, sign-ext, reference-types, multivalue, bulk-memory-opt
|
||||
)
|
||||
|
||||
96
sqlite3/libc/libc_test.go
Normal file
96
sqlite3/libc/libc_test.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package libc
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
)
|
||||
|
||||
//go:embed libc.wasm
|
||||
var binary []byte
|
||||
|
||||
const (
|
||||
size = 1024 * 1024 * 4
|
||||
ptr1 = 1024 * 1024
|
||||
ptr2 = ptr1 + size
|
||||
)
|
||||
|
||||
var (
|
||||
memory []byte
|
||||
module api.Module
|
||||
memset api.Function
|
||||
memcpy api.Function
|
||||
memcmp api.Function
|
||||
)
|
||||
|
||||
func call(fn api.Function, arg ...uint64) {
|
||||
fn.CallWithStack(context.Background(), arg)
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
ctx := context.Background()
|
||||
|
||||
runtime := wazero.NewRuntime(ctx)
|
||||
mod, err := runtime.Instantiate(ctx, binary)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
module = mod
|
||||
memset = mod.ExportedFunction("memset")
|
||||
memcpy = mod.ExportedFunction("memcpy")
|
||||
memcmp = mod.ExportedFunction("memcmp")
|
||||
memory, _ = mod.Memory().Read(0, mod.Memory().Size())
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func Benchmark_memset(b *testing.B) {
|
||||
clear(memory)
|
||||
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
call(memset, ptr1, 3, size)
|
||||
}
|
||||
b.StopTimer()
|
||||
|
||||
for i, v := range memory[ptr1 : ptr1+size] {
|
||||
if v != 3 {
|
||||
b.Fatal(i, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_memcpy(b *testing.B) {
|
||||
clear(memory)
|
||||
call(memset, ptr2, 5, size)
|
||||
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
call(memcpy, ptr1, ptr2, size)
|
||||
}
|
||||
b.StopTimer()
|
||||
|
||||
for i, v := range memory[ptr1 : ptr1+size] {
|
||||
if v != 5 {
|
||||
b.Fatal(i, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_memcmp(b *testing.B) {
|
||||
clear(memory)
|
||||
call(memset, ptr1, 7, size)
|
||||
call(memset, ptr2, 7, size)
|
||||
call(memset, ptr2+size/2, 5, size)
|
||||
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
call(memcmp, ptr1, ptr2, size)
|
||||
}
|
||||
b.StopTimer()
|
||||
}
|
||||
@@ -3,9 +3,19 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__wasm_bulk_memory__)
|
||||
#define memset __builtin_memset
|
||||
#define memcpy __builtin_memcpy
|
||||
#define memmove __builtin_memmove
|
||||
|
||||
void *memset(void *dest, int c, size_t n) {
|
||||
return __builtin_memset(dest, c, n);
|
||||
}
|
||||
|
||||
void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
|
||||
return __builtin_memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
void *memmove(void *dest, const void *src, size_t n) {
|
||||
return __builtin_memmove(dest, src, n);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define ONES (~(uintmax_t)(0) / UCHAR_MAX)
|
||||
|
||||
Reference in New Issue
Block a user