By just reducing cost of doing allocations (but still allocating the same number of structs) on some of the hot paths it sped up making of the AST tree by 1.5x
If you can use this approach for the entire parser I imagine the gains would be much more significant
That's great! I see you use `sync.Pool`, which is way safer alternative. However, I wasn't able to secure much of performance gains for linked list benchmark using sync.Pool. It's not even clear how much objects it will contain ready to go. On the other hand, sync.Pool docs suggest to implement own free list for small short-living objects. I wonder what do they mean and how it should look like?
I actually only use sync.Pool to allocate large chunks at a time, so the cost of sync.Pool calls is minimal. The main benefit comes from allocating (and freeing) the big chunk instead of individual structs, without having to worry about object lifetimes.
Correction: no, looks like I do indeed call it each time. Well, it's still more efficient I guess :))
By just reducing cost of doing allocations (but still allocating the same number of structs) on some of the hot paths it sped up making of the AST tree by 1.5x
If you can use this approach for the entire parser I imagine the gains would be much more significant