github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/compiler/compiler_bench_test.go (about) 1 package compiler 2 3 import ( 4 "bytes" 5 "fmt" 6 "testing" 7 "unsafe" 8 9 "github.com/wasilibs/wazerox/internal/asm" 10 "github.com/wasilibs/wazerox/internal/testing/require" 11 "github.com/wasilibs/wazerox/internal/wasm" 12 "github.com/wasilibs/wazerox/internal/wazeroir" 13 ) 14 15 func BenchmarkCompiler_compileMemoryCopy(b *testing.B) { 16 sizes := []uint32{5, 17, 128, 10000, 64000} 17 18 for _, size := range sizes { 19 for _, overlap := range []bool{false, true} { 20 b.Run(fmt.Sprintf("%v-%v", size, overlap), func(b *testing.B) { 21 env := newCompilerEnvironment() 22 buf := asm.CodeSegment{} 23 defer func() { 24 require.NoError(b, buf.Unmap()) 25 }() 26 27 mem := env.memory() 28 testMem := make([]byte, len(mem)) 29 for i := 0; i < len(mem); i++ { 30 mem[i] = byte(i) 31 testMem[i] = byte(i) 32 } 33 34 compiler := newCompiler() 35 compiler.Init(&wasm.FunctionType{}, &wazeroir.CompilationResult{HasMemory: true}, false) 36 err := compiler.compilePreamble() 37 require.NoError(b, err) 38 39 var destOffset, sourceOffset uint32 40 if !overlap { 41 destOffset, sourceOffset = 1, 777 42 } else { 43 destOffset, sourceOffset = 777, 1 44 } 45 46 err = compiler.compileConstI32(operationPtr(wazeroir.NewOperationConstI32(destOffset))) 47 require.NoError(b, err) 48 err = compiler.compileConstI32(operationPtr(wazeroir.NewOperationConstI32(sourceOffset))) 49 require.NoError(b, err) 50 err = compiler.compileConstI32(operationPtr(wazeroir.NewOperationConstI32(size))) 51 require.NoError(b, err) 52 err = compiler.compileMemoryCopy() 53 require.NoError(b, err) 54 err = compiler.(compilerImpl).compileReturnFunction() 55 56 require.NoError(b, err) 57 _, err = compiler.compile(buf.NextCodeSection()) 58 require.NoError(b, err) 59 60 env.execBench(b, buf.Bytes()) 61 62 for i := 0; i < b.N; i += 1 { 63 copy(testMem[destOffset:destOffset+size], testMem[sourceOffset:sourceOffset+size]) 64 } 65 66 if !bytes.Equal(mem, testMem) { 67 b.FailNow() 68 } 69 }) 70 } 71 } 72 } 73 74 func BenchmarkCompiler_compileMemoryFill(b *testing.B) { 75 sizes := []uint32{5, 17, 128, 10000, 64000} 76 77 for _, size := range sizes { 78 b.Run(fmt.Sprintf("%v", size), func(b *testing.B) { 79 env := newCompilerEnvironment() 80 buf := asm.CodeSegment{} 81 defer func() { 82 require.NoError(b, buf.Unmap()) 83 }() 84 85 compiler := newCompiler() 86 compiler.Init(&wasm.FunctionType{}, &wazeroir.CompilationResult{HasMemory: true}, false) 87 88 var startOffset uint32 = 100 89 var value uint8 = 5 90 91 err := compiler.compilePreamble() 92 require.NoError(b, err) 93 94 err = compiler.compileConstI32(operationPtr(wazeroir.NewOperationConstI32(startOffset))) 95 require.NoError(b, err) 96 err = compiler.compileConstI32(operationPtr(wazeroir.NewOperationConstI32(uint32(value)))) 97 require.NoError(b, err) 98 err = compiler.compileConstI32(operationPtr(wazeroir.NewOperationConstI32(size))) 99 require.NoError(b, err) 100 err = compiler.compileMemoryFill() 101 require.NoError(b, err) 102 err = compiler.(compilerImpl).compileReturnFunction() 103 require.NoError(b, err) 104 _, err = compiler.compile(buf.NextCodeSection()) 105 require.NoError(b, err) 106 107 mem := env.memory() 108 testMem := make([]byte, len(mem)) 109 for i := 0; i < len(mem); i++ { 110 mem[i] = byte(i) 111 testMem[i] = byte(i) 112 } 113 114 env.execBench(b, buf.Bytes()) 115 116 for i := startOffset; i < startOffset+size; i++ { 117 testMem[i] = value 118 } 119 120 for i := 0; i < len(mem); i++ { 121 require.Equal(b, mem[i], testMem[i], "mem != %d at offset %d", value, i) 122 } 123 }) 124 } 125 } 126 127 func (j *compilerEnv) execBench(b *testing.B, codeSegment []byte) { 128 executable := requireExecutable(codeSegment) 129 b.StartTimer() 130 for i := 0; i < b.N; i++ { 131 nativecall( 132 uintptr(unsafe.Pointer(&executable[0])), 133 j.ce, j.moduleInstance, 134 ) 135 } 136 b.StopTimer() 137 }