-
-
Notifications
You must be signed in to change notification settings - Fork 219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Possible memory leak #25
Comments
Any update on this? |
@bem7 thanks for reporting; I’ll take a closer look and see what is happening for this use-case. |
Yes, it was the latest version. Sounds great. Let me know if there’s a way I can help.
|
@bem7 So I could easily replicate your issue; What's happening is that the Go Garbage Collector is not finding the If I manually call func BenchmarkIsolateInitialization(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
vm, _ := v8go.NewIsolate()
ctx, _ := v8go.NewContext(vm)
ctx.RunScript(script, "main.js")
str, _ := json.Marshal(makeObject())
cmd := fmt.Sprintf("process(%s)", str)
ctx.RunScript(cmd, "cmd.js")
ctx.Close() // this calls the finalizer function
vm.Close() // this calls the finalizer funtion
}
} Please note that the Need to have a think if adding |
Another approach might be to dig-in to find why the GC can't deallocate the Isolate. |
Because the allocations happen in the CGO world it makes it slightly harder to profile the memory usage (I wish I could just use pprof); but I tried running the benchmarks continuously for some time and could see the memory flatline around the 14MB mark using If you could run any tests against this PR, that would be helpful? |
@rogchap Just tested the PR and I'm observing similar memory usage. However, consider this slightly different benchmark, which will still consume 100s MBs of memory:
It seems that – barring figuring out why GC is failing – it's necessary to manually close both isolates and contexts (as you suggested in a previous comment). I don't necessarily think it's that big of a deal. It wouldn't be uncommon to create isolates and contexts in two different places in the code. And for one-off use, calls like Is there a reason you're calling the close function |
@bem7 Thanks for testing. Yea; I’ll add a |
I've added a |
@rogchap Works great! I was thinking about why the GC is failing. My hypothesis: Go doesn't know about the allocations being made in v8, it only tracks the size of the |
Read on variable Go finalizers are not ideal destructors. There are too many cases when they don't run. I wouldn't use them in production. Instead, provide 1-to-1 Go mappings to C++. |
This is exactly what happens. Go memory usage is growing very slowly while the C memory usage is growing very quickly, so the Go garbage collector never bothers to run and the C memory usage gets enormous. That is why finalizers can lead to broken programs. One has to be aware of the limitations. Generally, I think V8 |
@rogchap For what it's worth, your PR fixes an issue I was just about to raise before seeing this existing issue. On MacOS, it would consistently crash with a SIGSEGV and with PR #26 it now works fine. For what it's worth, I hadn't yet bothered looking into memory usage - nor did I even change the code beyond the |
Closing as with #26 |
Hi,
I've been playing with v8go, and so far liking it a lot!
I'm running into a fatal error when benchmarking isolate initialization (and running a simple workload). Here's my code:
When running it with
n = 1000
, it completes just fine. But running withn = 10000
gives me this error:Monitoring the process, I noticed it's allocating several gigabytes of memory until eventually crashing.
Moving the initialization of
cmd
out of the loop prevents the crash, but the process still racks up lots of memory. It seems to me that this whole process should be lightweight, as it never runs more than a single isolate at once. Would appreciate some thoughts :)The text was updated successfully, but these errors were encountered: