github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/integration_test/engine/memleak_test.go (about)

     1  package adhoc
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"runtime"
     8  	"strconv"
     9  	"testing"
    10  	"time"
    11  
    12  	wazero "github.com/wasilibs/wazerox"
    13  	"github.com/wasilibs/wazerox/experimental/opt"
    14  )
    15  
    16  func TestMemoryLeak(t *testing.T) {
    17  	if testing.Short() {
    18  		t.Skip("skipping memory leak test in short mode.")
    19  	}
    20  
    21  	for _, tc := range []struct {
    22  		name     string
    23  		isWazevo bool
    24  	}{
    25  		{"compiler", false},
    26  		{"wazevo", true},
    27  	} {
    28  		tc := tc
    29  
    30  		if tc.isWazevo && runtime.GOARCH != "arm64" {
    31  			t.Skip("skipping wazevo memory leak test on non-arm64.")
    32  		}
    33  
    34  		t.Run(tc.name, func(t *testing.T) {
    35  			duration := 5 * time.Second
    36  			t.Logf("running memory leak test for %s", duration)
    37  
    38  			ctx, cancel := context.WithTimeout(context.Background(), duration)
    39  			defer cancel()
    40  
    41  			for ctx.Err() == nil {
    42  				if err := testMemoryLeakInstantiateRuntimeAndModule(tc.isWazevo); err != nil {
    43  					log.Panicln(err)
    44  				}
    45  			}
    46  
    47  			var stats runtime.MemStats
    48  			runtime.GC()
    49  			runtime.ReadMemStats(&stats)
    50  
    51  			if stats.Alloc > (100 * 1024 * 1024) {
    52  				t.Errorf("wazero used more than 100 MiB after running the test for %s (alloc=%d)", duration, stats.Alloc)
    53  			}
    54  			fmt.Println(stats.Alloc)
    55  		})
    56  	}
    57  }
    58  
    59  func testMemoryLeakInstantiateRuntimeAndModule(isWazevo bool) error {
    60  	ctx := context.Background()
    61  
    62  	var r wazero.Runtime
    63  	if isWazevo {
    64  		c := opt.NewRuntimeConfigOptimizingCompiler()
    65  		r = wazero.NewRuntimeWithConfig(ctx, c)
    66  	} else {
    67  		r = wazero.NewRuntime(ctx)
    68  	}
    69  	defer r.Close(ctx)
    70  
    71  	hostBuilder := r.NewHostModuleBuilder("test")
    72  
    73  	for i := 0; i < 100; i++ {
    74  		hostBuilder.NewFunctionBuilder().WithFunc(func() uint32 { return uint32(i) }).Export(strconv.Itoa(i))
    75  	}
    76  
    77  	hostMod, err := hostBuilder.Instantiate(ctx)
    78  	if err != nil {
    79  		return err
    80  	}
    81  	if err = hostMod.Close(ctx); err != nil {
    82  		return err
    83  	}
    84  
    85  	mod, err := r.InstantiateWithConfig(ctx, memoryWasm,
    86  		wazero.NewModuleConfig().WithStartFunctions())
    87  	if err != nil {
    88  		return err
    89  	}
    90  	return mod.Close(ctx)
    91  }