Curious to know what people are building where you need to optimise like this? eg Struct Field Alignment https://goperf.dev/01-common-patterns/fields-alignment/#avoi...
Go Optimization Guide
41–50 of 173 posts
Re: Go Optimization Guide
#42Re: Go Optimization Guide
#43Re: Go Optimization Guide
#44Earlier quoted context omitted.
No. If you have a moving multi generational GC, allocation is literally just an increment for short lived objects.
If you have a moving, generational GC, then all the benefits of fast allocation are lost due to data moving and costly memory barriers.
Re: Go Optimization Guide
#45 pool := sync.Pool{
New: func() any { return 42 }
}
a := pool.Get()
pool.Put("hello")
pool.Put(struct{}{})
b := pool.Get()
c := pool.Get()
d := pool.Get()
fmt.Println(a, b, c, d)
Of course, the answer is that this API existed before generics so it just takes and returns `any` (née `interface{}`). It just feels as though golang might be strongly typed in principle, but in practice there are APIs left and rigth that escape out of the type system and lose all of the actual benefits of having it in the first place.Is a type system all that helpful if you have to keep turning it off any time you want to do something even slightly interesting?
Also I can't help but notice that there's no API to reset values to some initialized default. Shouldn't there be some sort of (perhaps optional) `Clear` callback that resets values back to a sane default, rather than forcing every caller to remember to do so themselves?
Re: Go Optimization Guide
#46Earlier quoted context omitted.
I guess if you allocate more than you need upfront that it could increase memory usage.
I don't get it. The pool uses weak pointers under the hood right? If you allocate too much up front, the stuff you don't need will get garbage collected. It's no worse than doing the same without a pool, right?
If that's the case, it's usually better to have non-global pools, pool ranges, drop things after a certain capacity, etc.:
https://github.com/golang/go/issues/23199 https://github.com/golang/go/blob/7e394a2/src/net/http/h2_bu...
Re: Go Optimization Guide
#47You can often fool yourself by using sync.Pool. pprof looks great because no allocs in benchmarks but memory usage goes through the roof. It's important to measure real world benefits, if any, and not just synthetic benchmarks.
Re: Go Optimization Guide
#48Every perf guide recommends to minimize allocations to reduce GC times, but if you look at pprof of a Go app, GC mark phase is what takes time, not GC sweep. GC mark always starts with known live roots (goroutine stacks, globals, etc) and traverse references from there colouring every pointer. To minimize GC time it is best to avoid _long living_ allocations. Short lived allocations, those which GC mark phase will ne…
Are you including in this analysis the amount of time/resources it takes to allocate? GC isn't the only thing you want to minimize for when you're making a high performance system.
My comment is more about "reduce allocations to reduce GC pressure" advice seen everywhere. It doesn't tell the whole story. Short lived allocation doesn't introduce any GC pressure: you'll be hard pressed to see GC sweep phase on pprof without zooming. People take this advice, spend time and energy hunting down allocations, just to see that total GC time remained the same after all that effort, because they were focusing on wrong type of allocations.
Re: Go Optimization Guide
#49Curious to know what people are building where you need to optimise like this? eg Struct Field Alignment https://goperf.dev/01-common-patterns/fields-alignment/#avoi...
Re: Go Optimization Guide
#50Checking out the first example—object pools—I was initially blown away that this is not only possible but it produces no warnings of any kind: pool := sync.Pool{ New: func() any { return 42 } } a := pool.Get() pool.Put("hello") pool.Put(struct{}{}) b := pool.Get() c := pool.Get() d := pool.Get() fmt.Println(a, b, c, d) Of course, the answer is that this API existed before generics so it just takes and returns `any` (…
> Also I can't help but notice that there's no API to reset values to some initialized default.
That's what the New function does, isn't it?
BTW, the code you posted isn't syntactically correct. It needs a comma on the second line.