wa-lang.org/wazero@v1.0.2/internal/integration_test/vs/bench_allocation.go (about)

     1  package vs
     2  
     3  import (
     4  	"bytes"
     5  	_ "embed"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"wa-lang.org/wazero/internal/testing/require"
    10  )
    11  
    12  var (
    13  	// allocationWasm is compiled from ../../../examples/allocation/tinygo/testdata/src/greet.go
    14  	// We can't use go:embed as it is outside this directory. Copying it isn't ideal due to size and drift.
    15  	allocationWasmPath = "../../../examples/allocation/tinygo/testdata/greet.wasm"
    16  	allocationWasm     []byte
    17  	allocationParam    = "wazero"
    18  	allocationResult   = []byte("wasm >> Hello, wazero!")
    19  	allocationConfig   *RuntimeConfig
    20  )
    21  
    22  func init() {
    23  	allocationWasm = readRelativeFile(allocationWasmPath)
    24  	allocationConfig = &RuntimeConfig{
    25  		ModuleName: "greet",
    26  		ModuleWasm: allocationWasm,
    27  		FuncNames:  []string{"malloc", "free", "greet"},
    28  		NeedsWASI:  true, // Needed for TinyGo
    29  		LogFn: func(buf []byte) error {
    30  			if !bytes.Equal(allocationResult, buf) {
    31  				return fmt.Errorf("expected %q, but was %q", allocationResult, buf)
    32  			}
    33  			return nil
    34  		},
    35  	}
    36  }
    37  
    38  func allocationCall(m Module, _ int) error {
    39  	nameSize := uint32(len(allocationParam))
    40  	// Instead of an arbitrary memory offset, use Rust's allocator. Notice
    41  	// there is nothing string-specific in this allocation function. The same
    42  	// function could be used to pass binary serialized data to Wasm.
    43  	namePtr, err := m.CallI32_I32(testCtx, "malloc", nameSize)
    44  	if err != nil {
    45  		return err
    46  	}
    47  
    48  	// The pointer is a linear memory offset, which is where we write the name.
    49  	if err = m.WriteMemory(testCtx, namePtr, []byte(allocationParam)); err != nil {
    50  		return err
    51  	}
    52  
    53  	// Now, we can call "greet", which reads the string we wrote to memory!
    54  	if err = m.CallI32I32_V(testCtx, "greet", namePtr, nameSize); err != nil {
    55  		return err
    56  	}
    57  
    58  	// This pointer was allocated by Rust, but owned by Go, So, we have to
    59  	// deallocate it when finished
    60  	return m.CallI32_V(testCtx, "free", namePtr)
    61  }
    62  
    63  func RunTestAllocation(t *testing.T, runtime func() Runtime) {
    64  	testCall(t, runtime, allocationConfig, testAllocationCall)
    65  }
    66  
    67  func testAllocationCall(t *testing.T, m Module, instantiation, iteration int) {
    68  	err := allocationCall(m, iteration)
    69  	require.NoError(t, err, "instantiation[%d] iteration[%d] failed: %v", instantiation, iteration, err)
    70  }
    71  
    72  func RunTestBenchmarkAllocation_Call_CompilerFastest(t *testing.T, vsRuntime Runtime) {
    73  	runTestBenchmark_Call_CompilerFastest(t, allocationConfig, "Allocation", allocationCall, vsRuntime)
    74  }
    75  
    76  func RunBenchmarkAllocation(b *testing.B, runtime func() Runtime) {
    77  	benchmark(b, runtime, allocationConfig, allocationCall)
    78  }