prattmic
Joined 14 years ago
Joined 14 years ago
There are lots of cases in the allocator that are conditional on size class (tiny allocations have a bunch of special cases, as do large allocations). Pointer/no-pointer allocations also have lots of special cases.
In the specialized functions, these conditionals become constant and lots of code falls away. We don’t pay the cost for those comparisons anymore, plus since code size is smaller it is now more reasonable to inline callees a bit more aggressively.
Michael also put a lot of time into finding the right balance of code size. At first you want to specialize everything, but that is going to increase code size a lot and thus hurt icache performance. If I recall correctly, our initial version had a code size increase ~4x higher than what we ended up with in 1.27. The final version specializes far fewer size classes yet actually had better performance than the original version.
Regarding the ABI, we definitely see an improvement with static calls vs computing the size class in the runtime. If I recall correctly, it’s the indirect call to the specialized function through a lookup table that stalls the dynamic case.
https://lwn.net/Articles/1057561/ which goes on to explain that this was the motivation for git history.
-Joseph Heller, Catch-22
(It's basically an easter egg, but if you look at the source of the release notes, you will see that most entries in the release notes have an HTML comment referencing the Go CL or issue that the entry refers to.)
Not in New York, unfortunately. All of the stations have cell service, and one tunnel (14th Street L train tunnel under the East River), but everywhere else has no service between stations. It’s an annoying limitation that most cities seem to have fixed by now.
It certainly may be useful to define an specific ordering. Maps ordered by insertion time and maps ordered by key order are fairly common. But maps with these constraints probably won't be as fast as those with arbitrary ordering, so there is a trade-off decision to be made. A map constrained to the arbitrary ordering of the initial implementation is the worst of both worlds: difficult to make faster despite not having a particularly useful ordering.
As a concrete example, I am currently in the middle of rewriting Go's map implementation to use a more efficient design (https://go.dev/issue/54766). If Go hadn't randomized map iteration order this work would likely be impossible. It is unlikely we could completely change the design while keeping iteration order identical to the old implementation (assuming we want the new version to be faster at least).