github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/examples/concurrent-instantiation/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	_ "embed"
     6  	"fmt"
     7  	"log"
     8  	"sync"
     9  
    10  	"github.com/bananabytelabs/wazero"
    11  )
    12  
    13  // addWasm was generated by the following:
    14  //
    15  //	wasm-tools parse testdata/add.wat -o testdata/add.wasm
    16  //
    17  //go:embed testdata/add.wasm
    18  var addWasm []byte
    19  
    20  func main() {
    21  	// Choose the context to use for function calls.
    22  	ctx := context.Background()
    23  
    24  	// Create a new WebAssembly Runtime.
    25  	r := wazero.NewRuntime(ctx)
    26  	defer r.Close(ctx) // This closes everything this Runtime created.
    27  
    28  	// Compile the Wasm binary once so that we can skip the entire compilation time during instantiation.
    29  	compiledWasm, err := r.CompileModule(ctx, addWasm)
    30  	if err != nil {
    31  		log.Panicf("failed to compile Wasm binary: %v", err)
    32  	}
    33  
    34  	var wg sync.WaitGroup
    35  	const goroutines = 50
    36  	wg.Add(goroutines)
    37  
    38  	// Instantiate the Wasm module from `compiledWsam`, and invoke the exported "add" function concurrently.
    39  	for i := 0; i < goroutines; i++ {
    40  		go func(i int) {
    41  			defer wg.Done()
    42  
    43  			// Instantiate a new Wasm module from the already compiled `compiledWasm`.
    44  			instance, err := r.InstantiateModule(ctx, compiledWasm, wazero.NewModuleConfig().WithName(""))
    45  			if err != nil {
    46  				log.Panicf("[%d] failed to instantiate %v", i, err)
    47  			}
    48  
    49  			// Calculates "i + i" by invoking the exported "add" function.
    50  			result, err := instance.ExportedFunction("add").Call(ctx, uint64(i), uint64(i))
    51  			if err != nil {
    52  				log.Panicf("[%d] failed to invoke \"add\": %v", i, err)
    53  			}
    54  
    55  			// Ensure the addition "i + i" is actually calculated.
    56  			expected := uint64(i * 2)
    57  			if result[0] != expected {
    58  				log.Panicf("expected %d, but got %d", expected, result[0])
    59  			}
    60  
    61  			// Logs the result.
    62  			fmt.Println(expected)
    63  		}(i)
    64  	}
    65  
    66  	wg.Wait()
    67  }