Marshalling a string object ref to an actual value (before it can be used for string manipulations internally) must incur a fair bit of CPU overhead.
I guess they decided the unboxed memory savings were worth it.
Marshalling a string object ref to an actual value (before it can be used for string manipulations internally) must incur a fair bit of CPU overhead.
I guess they decided the unboxed memory savings were worth it.
I'll trust that they had good performance data that made them decide to do this. Still, I'm always a bit skeptical about these clever string tricks. It's an optimization that looks amazing in microbenchmarks but has costs in the real world. That's because you're adding a (potentially hard-to-predict) branch to every access to the string.
If your application constantly allocates and deallocates lots of tiny ASCII strings, this clever representation will be fantastic for you. However, if you use a mix of string sizes, tend to keep them around for awhile, and you do a lot of manipulations on those strings, you pay the branch-misprediction cost over and over.
They're extremely careful about the performance of objc_msgSend, because it's so significant to the overall performance of apps. The running time for a hot path message send is down to single digit CPU cycles. Any addition to that shows up pretty loudly. I'm sure they checked to make sure the check doesn't add too much overhead in real-world use, and that the wins are worth it.
The savings aren't just memory, it's probably a performance improvement too. Fewer allocations, fewer pointer indirections, and some operations (like equality checking) become O(1) instead of O(n) for these tiny strings.
I would think the avoidance of allocations and the pointer indirections are the big wins.