wasmerio / wasmer-go

🐹🕸️ WebAssembly runtime for Go
https://pkg.go.dev/github.com/wasmerio/wasmer-go
MIT License
2.83k stars 161 forks source link

How to release an instance? #269

Closed localvar closed 3 years ago

localvar commented 3 years ago

Summary

with the below code snippet, the virtual memory used by the application increases 6G in every iteration.

    wasmer.NewConfig()
    engine := wasmer.NewEngine()
    store := wasmer.NewStore(engine)
    module, _ := wasmer.NewModule(store, code)
    importObject := wasmer.NewImportObject()

    for {
        _, e := wasmer.NewInstance(module, importObject)
        if e != nil {
            fmt.Println("failed to create instance:", e.Error())
        }
        var b []byte = make([]byte, 1)
        fmt.Println("hit enter to continue..")
        os.Stdin.Read(b)
    }

Is there a way to release this memory? Thanks

Hywan commented 3 years ago

Hello,

That's a good question. I'm not a Go expert, so my answer might be incorrect or incomplete. I would suggest to force the GC to run, which will run the SetFinalizer registered function of the wasmer.Instance, and thus will free the memories, and everything else attached to the Instance.

Thoughts?

localvar commented 3 years ago

Thanks for the suggestion, I've tried a force GC, but it doesn't work, the virtual memory is still there. I also add some logs to the finalizer, and can confirm it is called during the GC.

Hywan commented 3 years ago

So, if the Instance is correctly dropped, then everything is alright, and it's up to the Go runtime or the OS to truncate the virtual memory, but it's not super critical, or is it?

localvar commented 3 years ago

Yes, not critical. But after more investigation, it doesn't look like a Go or OS issue. if the wasm code is compiled from below wat then everything is ok:

(module
    (func (export "foo")
    )
)

but when it is compiled from the below C code then I can see the issue:

void foo() {
}

The C code is compiled by emcc version 2.0.21 by emcc foo.c -O3 -o foo.wasm -s EXPORTED_FUNCTIONS=_foo --no-entry and my OS version is Ubuntu 20.04.1 LTS.

BTW, I met the same issue in wasmtime.

Hywan commented 3 years ago

Can you please share with me the emscripten-generated Wasm module?

localvar commented 3 years ago

Github doesn't allow me to attach a wasm file, so I convert it to wat format:


(module
  (type (;0;) (func (result i32)))
  (type (;1;) (func))
  (type (;2;) (func (param i32)))
  (type (;3;) (func (param i32) (result i32)))
  (func (;0;) (type 1)
    nop)
  (func (;1;) (type 0) (result i32)
    global.get 0)
  (func (;2;) (type 2) (param i32)
    local.get 0
    global.set 0)
  (func (;3;) (type 3) (param i32) (result i32)
    global.get 0
    local.get 0
    i32.sub
    i32.const -16
    i32.and
    local.tee 0
    global.set 0
    local.get 0)
  (func (;4;) (type 0) (result i32)
    i32.const 1024)
  (table (;0;) 2 2 funcref)
  (memory (;0;) 256 256)
  (global (;0;) (mut i32) (i32.const 5243920))
  (export "memory" (memory 0))
  (export "foo" (func 0))
  (export "_initialize" (func 0))
  (export "__indirect_function_table" (table 0))
  (export "__errno_location" (func 4))
  (export "stackSave" (func 1))
  (export "stackRestore" (func 2))
  (export "stackAlloc" (func 3))
  (elem (;0;) (i32.const 1) func 0))
``
Hywan commented 3 years ago

Thank you. I'll investigate as soon as I have time. By reading the given wat, nothing pops in my mind for the moment.

Hywan commented 3 years ago

In #277, I'm fixing some memory leaks on the Go land. It appears that runtime.SetFinalizer isn't working as expected in all scenarios. See #262 too.

Celebraty commented 1 year ago

@localvar is your issue soluted by the latest release? i still have this problem