/ go Public
runtime: allocate no-escape map buckets to the stack more aggressively #58214
Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Whenever a map is created and identified as not escaping the called function,
I observe that the first bucket (8 entries) comes literally for free on the stack.
However, when the map is grown to a higher number of buckets (e.g. make(map[int]string,9) or grown dynamically),
the next buckets are allocated on the heap, then garbage-collected.
This makes a huge difference for relatively small maps, but not as small as the tiny 8 slots.
The same occurs, whether the map size is known or not known at compile time, yet correctly detected as not escaping the function.
I suggest allocating buckets of unescaped maps to the stack more aggressively and only resorting to the heap
when the stack is getting close to its max.
The criterion to switch from stack to heap should be determined at runtime and could be either when the stack is maxed out (super aggressive) or merely when allocating the new bucket would require a new stack segment (super conservative).
In either case, I believe this improvement would largely speed up the dozens of small map-based utility functions that we use routinely (see an example below).
In the 3 simplistic examples below (all inspired by real-life utilities, such as "deduplicate an input slice", but much simplified here...), the compiler correctly identifies the map as not escaping the func.
In all examples, if the input size (variable or const) is <= 8, no allocation on the heap takes place (the first bucket comes for free).
In all examples, if an extra bucket is needed, either by calling make with a hint or by growing the map, it is always allocated on the heap.
The text was updated successfully, but these errors were encountered: