|
|
|
|
|
by jerf
3858 days ago
|
|
Infrequently enough that it's usually premature optimization to spend too much time worrying about it. But in Go's core application space, high-load network applications, frequently enough that it's something you should be aware of, and there's a realistic chance of optimizing everything else to the point that GC time becomes your biggest problem, even after the latest work on it. You'd still want to reach for mmm only after A: verifying that GC time really is your biggest problem via profiling and B: taking more normal steps to minimize overallocation first, because with value types Go has some tools (if not necessarily "a lot" of such tools, but definitely some) for dealing with that. But if you end up backed against the wall, this may be helpful. You could also arguably add a C: did you really mean to use a language with manual memory in the first place, or perhaps Rust? Or can you factor just the relevant bit out into such a language and interact via some RPC mechanism back to the Go code base? But as the situation becomes arbitrarily complicated there simply ceases to be a silver bullet. |
|
In this configuration, each incoming request means allocations inside Go's RPC package [1], which in turn means that a GC pass will be triggered if GC_PERCENT [2] has been reached, which in turn means that the GC will have to scan all of those long lived pointers (Go's GC is not generational), which in turn means a huge peak in response time.
This basically leaves me with three possible solutions:
- hack into Go's RPC package to minimize allocations, which is a huge price to pay just to delay the inevitable
- build my caches in a language that offers manual memory management, then query those via RPC from my Go services; but I don't want to add a new language into the mix
- provide a generic solution for manual memory management in Go, which is where we are now
[1] https://golang.org/pkg/net/rpc/
[2] https://golang.org/pkg/runtime/debug/#SetGCPercent