-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
runtime: high memory usage on Go 1.14 #37525
Comments
One other idea. We do tweak the GC percentage via |
@karalabe The most useful thing in this scenario would be a bunch of heap profiles from both Go 1.13 and Go 1.14 runs. That will tell us a lot about the difference in "used." I have a hunch it's not more total allocated bytes and instead it's more likely that objects are being kept alive longer. In working on #35112 I did run into GC pacing changes (as a result of an increased allocation rate in some cases) that caused more objects to stay alive, which snowballed into up to a 2x RSS increase. We made a GC pacing change to stave off the most severe effects but it could still cause an RSS increase in some cases. If it does turn out to be this, then my recommendation is to just lower GOGC until you reach an acceptable level of memory use per performance (for whatever that metric is; wall clock time, latency, throughput, etc.). The overall performance should still be similar or better. If not, we'll move on from there. The increase in "held" being larger than "used" could just be fragmentation scaling up, but it could also be #35788 playing a role. Let's tackle "used" first, the "held" increase might go away (or only be slight). |
I'm facing the same problem.
|
The fact that fewer GCs are happening suggests to me a snowball scenario in live heap. Can you please share the output of running your benchmark/application with |
@mknyszek sure, here's the output! 1.13.3: 1.14: UPD: sorry, for some reasons I thought there were 87 GC cycles when I ran the tests for the first time, but now it's always 59 on each run. Still, the difference is huge. |
@pijng Thanks for the prompt reply! So one thing I'll note is that 1.13.3 has a 1 GiB heap still, which doesn't square quite right with your 80 MiB number. Could you explain more how you obtained that? In Go 1.14, it looks like a few GCs end up having larger heaps (1.6 GiB) so there's still a clear peak memory use increase. It almost seems like there's an out-running happening here; the heap goal of e.g. GC 4 is 1025 MiB and then suddenly the next GC starts at 1683 MiB of heap which is very off. The 1.13.3 trace suggests your application isn't just suddenly making a 600 MiB allocation (which is the usual way something like this might happen), so instead it seems like the GC start condition is being missed. Also, could you re-run the Go 1.14 one with |
@mknyszek I'm looking at the "Physical memory" of my process on the macos' built-in activity monitor. That's where I got the numbers from. I'm not experienced enough in this matter, so if you can tell me a proper way to obtain a helpful stats – I'll make sure to do it :) Output with 1.14 |
@pijng I think I have a root cause for your problem and I submitted a new issue. We should continue the conversation there, since it may be unrelated to this issue. @karalabe Given that you mentioned that you tweak GC percent, what do you tweak it to? Based on the value, your problem may be the same as #37927 (but I don't want to assume). |
@mknyszek Our GOGC tweak is https://github.com/ethereum/go-ethereum/blob/613af7ceea0f94b92f0e63e8db3a5f5926421087/cmd/geth/main.go#L288 I.e. |
@karalabe OK! Then it seems to me like this could definitely be #37927. Could you try running your application/benchmark against a Go toolchain with the following patch? https://go-review.googlesource.com/c/go/+/223937 |
Can confirm that the patch released in Go 1.14.2 indeed fixes the spurious memory blowup. Thanks! |
What version of Go are you using (
go version
)?1.13.8 vs 1.14
Does this issue reproduce with the latest release?
Yes
What did you do?
I wanted to benchmark the go-etheruem full sync performance with the new Go release vs. the old one. Speed wise Go 1.14 is maybe 10-15% faster, but that's not what this issue is about.
What did you expect to see?
Faster execution at the same memory usage.
What did you see instead?
Side by side, go-ethereum built with:
runtime.MemStats.Alloc
) 7.5GB RAM and held (runtime.MemStats.HeapSys - runtime.MemStats.HeapReleased
) 9GBruntime.MemStats.Alloc
) 8.5GB RAM and held (runtime.MemStats.HeapSys - runtime.MemStats.HeapReleased
) 11GBI've ran the tests on 4 VMs (two on Go 1.13 and two on Go 1.14), swapping the Go builds and restarting after a day to avoid false positives due to VM asymmetries. The results were the same on all 4 comparison runs. Go 1.14 was 10% faster and used significantly more memory.
At this point I'm unsure how I could help debug this further. Have there been any memory allocation changes made in Go 1.14 that could point towards heavier use? We do maintain significant in-memory caches, some large blobs, some tiny tiny slices. Perhaps some internal map field got more expensive?
The text was updated successfully, but these errors were encountered: