github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/iextengine/wazero/README.md (about) 1 # iextenginewasm 2 3 ## Basic Usage 4 See [Basic Usage Test](./impl_test.go) 5 6 ## Design 7 ```mermaid 8 erDiagram 9 ExtSrcFile }|..|| ExtensionsTinygoLib: "imports from public repo" 10 ExtensionsTinygoLib ||..|| ReadFromState: "used to" 11 ExtensionsTinygoLib ||..|| CreateIntents: "used to" 12 ReadFromState ||..|| FuncsExportedByWasmEngine: "internally calls" 13 CreateIntents ||..|| FuncsExportedByWasmEngine: "internally calls" 14 FuncsExportedByWasmEngine ||..|| ExtensionIO: "access to" 15 ExtensionsTinygoLib ||--|{ FuncsImportedByWasmEngine: "has" 16 FuncsImportedByWasmEngine ||--|| WasmAbiVersion: "has" 17 FuncsImportedByWasmEngine ||--|| WasmOnReadValue: "has" 18 FuncsImportedByWasmEngine ||--|| MemoryInfoFuncs: "has" 19 FuncsExportedByWasmEngine ||--|| WazeroExtensionEngine: "part of" 20 WasmAbiVersion ||..|| WazeroExtensionEngine: "used by" 21 WasmOnReadValue ||..|| WazeroExtensionEngine: "callback used by" 22 MemoryInfoFuncs ||..|| WasmEngineTests: "used by" 23 ``` 24 25 ### Principles: No Garbage Collection & Restore Memory 26 [Benchmarks show](https://github.com/heeus/core/blob/fdf52bcc6384657f214a492e8afac12c2bbaeaf6/iextenginewasm/impl_benchmark_test.go#L83) that tinygo garbage collection performance is extremely slow. Instead of making garbage collection, it is more effective to restore engine memory state when the heap is over ([benchmark1](https://github.com/heeus/core/blob/fdf52bcc6384657f214a492e8afac12c2bbaeaf6/iextenginewasm/impl_benchmark_test.go#L158), [benchmark2](https://github.com/heeus/core/blob/fdf52bcc6384657f214a492e8afac12c2bbaeaf6/iextenginewasm/impl_benchmark_test.go#L198)). 27 We are allowed to do this since extensions are pure functions by design. 28 29 Technical solution: 30 - `ExtBuildFile` compiles TinyGo sources to WASM with garbage collection [disabled (gc=leaking)](https://tinygo.org/docs/reference/usage/important-options/) 31 - the `exttinygo` library is developed to minimize heap allocations 32 - after WazeroExtensionEngine is initialized, the memory backup is saved internally; 33 - after ANY error engine automatically restores it's memory from backup 34 35 Restore benchmarks 36 ``` 37 goos: linux 38 goarch: amd64 39 pkg: github.com/heeus/core/iextenginewazero 40 cpu: 12th Gen Intel(R) Core(TM) i7-12700 41 Benchmark_Recover/2Mib-1%-20 491917 2041 ns/op 0 B/op 0 allocs/op 42 Benchmark_Recover/2Mib-50%-20 17457 68422 ns/op 0 B/op 0 allocs/op 43 Benchmark_Recover/2Mib-100%-20 18838 64025 ns/op 0 B/op 0 allocs/op 44 Benchmark_Recover/8Mib-100%-20 5707 204310 ns/op 7 B/op 0 allocs/op 45 Benchmark_Recover/100Mib-70%-20 6247 192577 ns/op 12 B/op 0 allocs/op 46 ``` 47 48 ### Memory Overflow 49 On memory overflow Invoke returns error like: 50 ``` 51 wasm error: unreachable 52 wasm stack trace: 53 .runtime.runtimePanic(i32,i32) 54 .runtime.alloc(i32) i32 55 .arrAppend() 56 .arrAppend.command_export() 57 ``` 58 59 ## Benchmarks 60 ### Extensions Code 61 ```go 62 //export oneGetOneIntent5calls 63 func oneGetOneIntent5calls() { 64 ext.GetValue(ext.KeyBuilder(ext.StorageEvent, ext.NullEntity)) 65 mail := ext.NewValue(ext.KeyBuilder(ext.StorageSendmail, ext.NullEntity)) 66 mail.PutString("from", "test@gmail.com") 67 } 68 69 //export oneGetNoIntents2calls 70 func oneGetNoIntents2calls() { 71 ext.GetValue(ext.KeyBuilder(ext.StorageEvent, ext.NullEntity)) 72 } 73 74 //export oneGetLongStr3calls 75 func oneGetLongStr3calls() { 76 value := ext.GetValue(ext.KeyBuilder(StorageTest, ext.NullEntity)) 77 value.AsString("500c") 78 } 79 80 //export doNothing 81 func doNothing() { 82 } 83 84 //export oneKey1call 85 func oneKey1call() { 86 ext.KeyBuilder(StorageTest2, ext.NullEntity) 87 } 88 ``` 89 ### Results 90 ``` 91 goos: linux 92 goarch: amd64 93 pkg: github.com/heeus/core/iextenginewasm 94 cpu: 12th Gen Intel(R) Core(TM) i7-12700 95 Benchmark_Extensions_NoGc/oneGetOneIntent5calls-20 882313 1292 ns/op 2108 B/op 25 allocs/op 96 Benchmark_Extensions_NoGc/oneGetNoIntents2calls-20 1685337 678.3 ns/op 1248 B/op 13 allocs/op 97 Benchmark_Extensions_NoGc/oneGetLongStr3calls-20 1682310 682.9 ns/op 1368 B/op 13 allocs/op 98 Benchmark_Extensions_NoGc/oneKey1call-20 4534441 253.6 ns/op 280 B/op 5 allocs/op 99 Benchmark_Extensions_NoGc/doNothing-20 17558064 62.54 ns/op 0 B/op 0 allocs/op 100 PASS 101 ``` 102