github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/iextengine/wazero/impl_benchmark_test.go (about)

     1  /*
     2    - Copyright (c) 2023-present unTill Software Development Group B.V.
     3      @author Michael Saigachenko
     4  */
     5  
     6  package iextenginewazero
     7  
     8  import (
     9  	"context"
    10  	"testing"
    11  
    12  	"github.com/voedger/voedger/pkg/appdef"
    13  	"github.com/voedger/voedger/pkg/iextengine"
    14  )
    15  
    16  func bench_purecall(b *testing.B) {
    17  	ctx := context.Background()
    18  	const simple = "simple"
    19  	moduleUrl := testModuleURL("./_testdata/allocs/pkg.wasm")
    20  	ee, err := testFactoryHelper(ctx, moduleUrl, []string{simple}, iextengine.ExtEngineConfig{MemoryLimitPages: 0xffff}, false)
    21  	if err != nil {
    22  		panic(err)
    23  	}
    24  	//ee.SetLimits(limits)
    25  
    26  	b.ResetTimer()
    27  	for n := 0; n < b.N; n++ {
    28  		if e := ee.Invoke(context.Background(), appdef.NewFullQName("test", simple), extIO); e != nil {
    29  			panic(e)
    30  		}
    31  	}
    32  	b.StopTimer()
    33  	ee.Close(ctx)
    34  }
    35  
    36  func bench_gc(b *testing.B, cycles int) {
    37  
    38  	const arrAppend = "arrAppend"
    39  	const arrReset = "arrReset"
    40  	ctx := context.Background()
    41  	moduleUrl := testModuleURL("./_testdata/allocs/pkggc.wasm")
    42  	ee, err := testFactoryHelper(ctx, moduleUrl, []string{arrAppend, arrReset}, iextengine.ExtEngineConfig{MemoryLimitPages: 0xffff}, false)
    43  	if err != nil {
    44  		panic(err)
    45  	}
    46  	//ee.SetLimits(limits)
    47  
    48  	b.ResetTimer()
    49  	for n := 0; n < b.N; n++ {
    50  		b.StopTimer()
    51  		for i := 0; i < cycles; i++ {
    52  			if e := ee.Invoke(context.Background(), appdef.NewFullQName("test", arrAppend), extIO); e != nil {
    53  				panic(e)
    54  			}
    55  		}
    56  		if e := ee.Invoke(context.Background(), appdef.NewFullQName("test", arrReset), extIO); e != nil {
    57  			panic(e)
    58  		}
    59  		b.StartTimer()
    60  		if e := ee.(*wazeroExtEngine).gc(testPkg, ctx); e != nil {
    61  			panic(e)
    62  		}
    63  	}
    64  
    65  	b.StopTimer()
    66  	ee.Close(ctx)
    67  
    68  }
    69  
    70  /*
    71  goos: linux
    72  goarch: amd64
    73  cpu: 12th Gen Intel(R) Core(TM) i7-12700
    74  Benchmark_GarbageCollection/simple-call-no-gc-20         	12560898	        82.73 ns/op	       0 B/op	       0 allocs/op
    75  Benchmark_GarbageCollection/gc-after-no-allocs-20        	      24	  47296163 ns/op	     888 B/op	      12 allocs/op
    76  Benchmark_GarbageCollection/gc-after-6-allocs-48b-20     	      25	  47137050 ns/op	     888 B/op	      12 allocs/op
    77  Benchmark_GarbageCollection/gc-after-20000-allocs-20     	      24	  46626752 ns/op	     888 B/op	      12 allocs/op
    78  */
    79  func Benchmark_GarbageCollection(b *testing.B) {
    80  	b.Run("simple-call-no-gc", func(b *testing.B) {
    81  		bench_purecall(b)
    82  	})
    83  	b.Run("gc-after-no-allocs", func(b *testing.B) {
    84  		bench_gc(b, 0)
    85  	})
    86  	b.Run("gc-after-6-allocs-48b", func(b *testing.B) {
    87  		bench_gc(b, 3)
    88  	})
    89  	b.Run("gc-after-20000-allocs", func(b *testing.B) {
    90  		bench_gc(b, 10000)
    91  	})
    92  }
    93  
    94  func bench_extensions(b *testing.B, gc bool, compile bool) {
    95  
    96  	funcs := []string{"oneGetOneIntent5calls", "oneGetNoIntents2calls", "oneGetLongStr3calls", "oneKey1call", "doNothing"}
    97  
    98  	ctx := context.Background()
    99  	wsm := "./_testdata/benchmarks/pkg.wasm"
   100  	if gc {
   101  		wsm = "./_testdata/benchmarks/pkggc.wasm"
   102  	}
   103  	moduleUrl := testModuleURL(wsm)
   104  	ee, err := testFactoryHelper(ctx, moduleUrl, funcs, iextengine.ExtEngineConfig{MemoryLimitPages: 0xffff}, compile)
   105  	if err != nil {
   106  		panic(err)
   107  	}
   108  	defer ee.Close(ctx)
   109  	for _, extname := range funcs {
   110  		ext := appdef.NewFullQName(testPkg, extname)
   111  		b.Run(extname, func(b *testing.B) {
   112  			b.ResetTimer()
   113  			for i := 0; i < b.N; i++ {
   114  				err := ee.Invoke(context.Background(), ext, extIO)
   115  				if err != nil {
   116  					panic(err)
   117  				}
   118  			}
   119  		})
   120  	}
   121  }
   122  
   123  /*
   124  goos: linux
   125  goarch: amd64
   126  cpu: 12th Gen Intel(R) Core(TM) i7-12700
   127  Benchmark_Extensions_NoGc/Compiler/oneGetOneIntent5calls-20         	  307974	      5875 ns/op	    2988 B/op	      55 allocs/op
   128  Benchmark_Extensions_NoGc/Compiler/oneGetNoIntents2calls-20         	  728787	      2519 ns/op	    1728 B/op	      26 allocs/op
   129  Benchmark_Extensions_NoGc/Compiler/oneGetLongStr3calls-20           	   90838	     48478 ns/op	  133032 B/op	      33 allocs/op
   130  Benchmark_Extensions_NoGc/Compiler/oneKey1call-20                   	 1000000	      1449 ns/op	     640 B/op	      15 allocs/op
   131  Benchmark_Extensions_NoGc/Compiler/doNothing-20                     	 3906926	       303.5 ns/op	     160 B/op	       3 allocs/op
   132  Benchmark_Extensions_NoGc/Interpreter/oneGetOneIntent5calls-20      	  267399	      5619 ns/op	    3156 B/op	      61 allocs/op
   133  Benchmark_Extensions_NoGc/Interpreter/oneGetNoIntents2calls-20      	  628476	      2079 ns/op	    1800 B/op	      29 allocs/op
   134  Benchmark_Extensions_NoGc/Interpreter/oneGetLongStr3calls-20        	   31657	     43928 ns/op	  133128 B/op	      37 allocs/op
   135  Benchmark_Extensions_NoGc/Interpreter/oneKey1call-20                	  924883	      1109 ns/op	     688 B/op	      17 allocs/op
   136  Benchmark_Extensions_NoGc/Interpreter/doNothing-20                  	 3429517	       327.5 ns/op	     184 B/op	       4 allocs/op
   137  */
   138  func Benchmark_Extensions_NoGc(b *testing.B) {
   139  	b.Run("Compiler", func(b *testing.B) {
   140  		bench_extensions(b, false, true)
   141  	})
   142  	b.Run("Interpreter", func(b *testing.B) {
   143  		bench_extensions(b, false, false)
   144  	})
   145  }
   146  func Skip_Benchmark_Extensions_WithGc(b *testing.B) {
   147  	bench_extensions(b, true, true)
   148  }
   149  
   150  func benchmarkRecover(b *testing.B, limitPages uint, expectedRuns int) {
   151  	const arrAppend2 = "arrAppend2"
   152  	ctx := context.Background()
   153  	moduleUrl := testModuleURL("./_testdata/allocs/pkg.wasm")
   154  	ee, err := testFactoryHelper(ctx, moduleUrl, []string{arrAppend2}, iextengine.ExtEngineConfig{MemoryLimitPages: limitPages}, true)
   155  	if err != nil {
   156  		panic(err)
   157  	}
   158  	defer ee.Close(ctx)
   159  
   160  	we := ee.(*wazeroExtEngine)
   161  	we.autoRecover = false
   162  
   163  	ext := appdef.NewFullQName(testPkg, arrAppend2)
   164  	for runs := 0; runs < expectedRuns; runs++ {
   165  		if err := ee.Invoke(context.Background(), ext, extIO); err != nil {
   166  			panic(err)
   167  		}
   168  	}
   169  
   170  	//we.backupMemory()
   171  
   172  	// the next call should fail
   173  	if err := ee.Invoke(context.Background(), ext, extIO); err == nil {
   174  		panic("err expected")
   175  	}
   176  
   177  	b.ResetTimer()
   178  	for i := 0; i < b.N; i++ {
   179  		we.recover(context.Background())
   180  	}
   181  }
   182  
   183  func benchmarkRecoverClean(b *testing.B, limitPages uint) {
   184  	ctx := context.Background()
   185  	moduleUrl := testModuleURL("./_testdata/allocs/pkg.wasm")
   186  	ee, err := testFactoryHelper(ctx, moduleUrl, []string{}, iextengine.ExtEngineConfig{MemoryLimitPages: limitPages}, true)
   187  	if err != nil {
   188  		panic(err)
   189  	}
   190  	defer ee.Close(ctx)
   191  	we := ee.(*wazeroExtEngine)
   192  	err = we.selectModule(testPkg)
   193  	if err != nil {
   194  		panic(err)
   195  	}
   196  	b.ResetTimer()
   197  	for i := 0; i < b.N; i++ {
   198  		we.recover(context.Background())
   199  	}
   200  }
   201  
   202  /*
   203  goos: linux
   204  goarch: amd64
   205  cpu: 12th Gen Intel(R) Core(TM) i7-12700
   206  Benchmark_Recover/2Mib-1%-20         	    6808	    168937 ns/op	 2221915 B/op	      61 allocs/op
   207  Benchmark_Recover/2Mib-50%-20        	    6200	    178177 ns/op	 2221917 B/op	      61 allocs/op
   208  Benchmark_Recover/2Mib-100%-20       	    6007	    191219 ns/op	 2233567 B/op	      63 allocs/op
   209  Benchmark_Recover/8Mib-100%-20       	    1484	    759637 ns/op	 8525009 B/op	      63 allocs/op
   210  Benchmark_Recover/100Mib-70%-20      	     117	   9026536 ns/op	100078791 B/op	      63 allocs/op
   211  */
   212  func Benchmark_Recover(b *testing.B) {
   213  	WasmPreallocatedBufferSize = 20000
   214  	b.Run("2Mib-1%", func(b *testing.B) { benchmarkRecoverClean(b, 0x20) })
   215  	WasmPreallocatedBufferSize = 1000000
   216  	b.Run("2Mib-50%", func(b *testing.B) { benchmarkRecoverClean(b, 0x20) })
   217  	b.Run("2Mib-100%", func(b *testing.B) { benchmarkRecover(b, 0x20, 3) })
   218  	b.Run("8Mib-100%", func(b *testing.B) { benchmarkRecover(b, 0x80, 26) })
   219  	b.Run("100Mib-70%", func(b *testing.B) { benchmarkRecover(b, 0x5f5, 209) })
   220  }
   221  
   222  func Benchmark_ArrayCopy(b *testing.B) {
   223  	const backupSize = 2000000
   224  	const heapSize = 10000000
   225  	backup := make([]byte, backupSize)
   226  	heap := make([]byte, heapSize)
   227  	_ = append(heap, 1)
   228  	b.Run("recommended", func(b *testing.B) {
   229  		b.ResetTimer()
   230  		for i := 0; i < b.N; i++ {
   231  			//_ = append(heap[0:0], backup...)
   232  			heap = make([]byte, len(backup))
   233  			copy(heap, backup)
   234  			b.StopTimer()
   235  			heap = make([]byte, heapSize)
   236  			_ = append(heap, 1)
   237  			b.StartTimer()
   238  		}
   239  	})
   240  	b.Run("shrink", func(b *testing.B) {
   241  		b.ResetTimer()
   242  		for i := 0; i < b.N; i++ {
   243  			heap = heap[0:len(backup)]
   244  			copy(heap[0:len(backup)], backup[0:])
   245  			b.StopTimer()
   246  			heap = make([]byte, heapSize)
   247  			_ = append(heap, 1)
   248  			b.StartTimer()
   249  		}
   250  	})
   251  
   252  }