second-state/dapr-wasm

It seems that memory leak occurs when image-api-go is called.

Taction opened this issue · 6 comments

I replace the web-port imageHandler func with the following code, to make it easier to observe(making more requests on one click). The memory usage of image-api-go is keeping growing when click classify.

type mock struct {}

func (m *mock)WriteHeader(statusCode int) {
}

func (m *mock)Header() http.Header {
	return nil
}
func (m *mock)Write(b []byte) (int, error) {
	return len(b), nil
}

func imageHandler(w http.ResponseWriter, r *http.Request) {
	println("imageHandler ....")
	body, err := ioutil.ReadAll(r.Body)

	if err != nil {
		println("error: ", err.Error())
		panic(err)
	}
	api := r.Header.Get("api")
	if api == "go" {
		daprClientSend(body, w)
		for i:=0;i<10;i++ {
			go func() {
				for i:=0;i<10;i++ {
					daprClientSend(body, &mock{})
				}
			}()
		}
	} else {
		httpClientSend(body, w)
	}
}

Thanks @Taction for reporting this issue.
I spent some time to reproduce it, it seems memory does not released after infer processed, here is a sample of memory I got:

image

@juntao Could you let any WasmEdge VM developer to have a look?

Here is the branch I used for testing:
https://github.com/chenyukang/dapr-wasm/tree/debug-mem

Here is the script used to reproduce it: https://github.com/chenyukang/dapr-wasm/blob/debug-mem/image-api-go/run_mem.sh

Thanks. @q82419 Can you look into this? It appears that the TF host function call has a memory leak. Thanks.

I think I can find the reason.
Let me fix on 0.9.0-rc1 in next week. Thanks.

Hi @chenyukang ,

I think the life-cycle in go may cause memory issue.
It's proper to use conf.Delete() directly after VM creation rather than use defer here,
And use vm.Delete() directly after VM execution rather than use defer here.
And the import objects created here should call the Delete() methods after VM deleted.

For the wasmedge_tensorflow_interface rust crate, I fixed the memory issue in rust and you can use the 0.2.2 version.
But after all, the memory leak in rust which will be compiled into WASM will all disappear after VM deletion.
I've overviewed the WasmEdge-Tensorflow and I cannot find the un-deallocated objects now.
Maybe we can look into and find the reason in the future, and the following graph shows that it's better after the adjustment:

Thanks.

Hi @chenyukang ,

I think the life-cycle in go may cause memory issue. It's proper to use conf.Delete() directly after VM creation rather than use defer here, And use vm.Delete() directly after VM execution rather than use defer here. And the import objects created here should call the Delete() methods after VM deleted.

For the wasmedge_tensorflow_interface rust crate, I fixed the memory issue in rust and you can use the 0.2.2 version. But after all, the memory leak in rust which will be compiled into WASM will all disappear after VM deletion. I've overviewed the WasmEdge-Tensorflow and I cannot find the un-deallocated objects now. Maybe we can look into and find the reason in the future, and the following graph shows that it's better after the adjustment:

Thanks.

Thanks for investigation, I will update the code as you suggested.
BTW, what is the difference between defer and manually call Delete.
Actually, the original code is Delete, I changed it to defer when debugging the issue.

I closed this issue since pr #20 is merged. Feel free to reopen this issue, if there is anything wrong. @Taction