12 ms·
Thanks for this, I just started getting into and writing Go code. I have a question that I don't remember being answered in any tutorial I've done so far. I'v
by legohead 7y ago
Thanks for this, I just started getting into and writing Go code.
I have a question that I don't remember being answered in any tutorial I've done so far. I've written a lot of C code and I typically make memory managed lists, so if I need a new common object I grab one from the list to avoid free/malloc as much as possible. Does Go do this automatically, or should I still do this on my own? I'm writing a long-running server, not a utility or something short lived.
- ryanworl 7y agoThat is still a useful tool in Go, but you don’t need to use it as much as you’d think. The GC is pretty good at short-lived objects. The canonical implementation is sync.Pool if you don’t want to build one yourself.
- weberc2 7y agoUsually I use pools to avoid the allocation cost. The GC sweep is not usually my problem.
- naikrovek 7y agoProfile it and see if it is a problem in Go, I would say. I don't know if the Go runtime has optimizations for this kind of thing inherently, and it might. Profile, and see.
- weberc2 7y agoThat's ... not helpful. I already profile and profiling indicates that allocations are slow and sweeps are fast. Go's optimization for this is escape analysis which is a best-effort attempt to put things on the stack. Because the stack analysis is naive (which isn't necessarily a bad thing), it means lots of things are still allocated on the heap, and those are the allocations I'm referring to.
- kasey_junk 7y agoThe bigger issue is usually stack vs heap allocation and it’s hard to reason about that. But the good news is that unlike a JIT system you can actually pretest golang escape analysis. Look at the -m gcflag to see what is escaping, then see if that is where the allocation hotspot is. If so see if you can get the escape to happen where you want. Otherwise you need to go no allocation. Notice that go actually gets _worse_ over time generally at heap allocation so it’s likrly worse than early profiles suggest.
- weberc2 7y ago> The bigger issue is usually stack vs heap allocation and it’s hard to reason about that. I don't think it's especially hard to reason about in the main cases, and when you're unsure (as you mention) you can actually print out the escapes. Would be really interesting to have an editor that would show you where things were escaping (although that could easily lead to premature optimization).
- GordonS 7y ago.NET has the ability to allocate on the stack, using `stackalloc` - does Go have a similar feature?
- nonane 7y agoTry using sync.Pool - it does the same thing: https://golang.org/pkg/sync/ https://golang.org/pkg/sync/
- axaxs 7y agoUp to you. If absolute performance is your reason, then you'll still end up writing your own pool like games seem to do. This is mainly to avoid the garbage collector. I'd try without first to see if that's really necessary.
- kevinconaway 7y agoThere is sync.Pool [0] but I wouldn't reach for it until you've profiled your application[1] and found that the specific allocation in question is a hot spot. As of now[2], they get cleared when a GC occurs so they can be a bit quirky to use in practice. This behavior is changing though [0] https://golang.org/pkg/sync/#Pool https://golang.org/pkg/sync/#Pool [1] https://blog.golang.org/profiling-go-programs https://blog.golang.org/profiling-go-programs [2] https://github.com/golang/go/issues/22950 https://github.com/golang/go/issues/22950
- shereadsthenews 7y agoThe Go authors have steadfastly refused to offer users any means of writing a CPU-local freelist, even though the utility of such things is obvious and evidenced by the fact that they use such things all over the runtime package. They just think that _you_ are too stupid to be allowed to do such a thing. Honestly with the attitude that the Go authors treat their users I don't know why anyone tries to write high performing code in that language. C++ is there, after all.
- adrianN 7y agoConcurrency is a bit easier in Go than in C++.
- shereadsthenews 7y agoDisagree. I can write a server in C++ that, with careful thought and a bit of planning, will be able to exploit the resources of the kind of 88-core dual-socket machines that are mainstream today. No amount of planning will allow me to write a Go program that does the same thing on the same machine. Small amounts of concurrency might seem easy in Go but lots of concurrency is hard.
- cdelsolar 7y agoWhere's the evidence that Go can't handle large amounts of concurrency?
- shereadsthenews 7y agoAll over my profiler. Go can deal with something embarrassingly parallel, same as any other language, but try getting it to scale up to high core counts with small RPCs is impossible, for the reasons the OP mentioned: you can't avoid its global allocator and you don't control the scheduler either. You will spend all of your CPU time in runtime.findrunnable and runtime.mallocgc.
- 7y ago
- kasey_junk 7y agoI’ve written them myself & used sync.pool. I’d carefully test where you are using them though as I’ve had an instance where an implementation went from lots better to lots worse than the naive allocation due to escape analysis getting better across a golang version upgrade.