State of String: ABI, Performance, Ergonomics, and You!

What is the expected existential inline buffer size going to wind up being? We sized it to 3 words specifically to fit string and array. It would be great to shrink that to 2 or 1 words.

I started discussion on the issue of determining the size of the inline storage here:

Thanks Arnold. In the absence of useful empirical data, you should go with analytic data. In Swift 1 we set the existential size to be big enough to hold string and array instances. Slice instances are not important to size to in this case IMO.

Getting it down to a 2 word existential buffer will be a big improvement.

@Chris: You state that it will be a big improvement, but it isn’t at all obvious to me that will be true. There is a clear tradeoff. A 2-word buffer will result in minor improvements for 1-2 word types and major regressions for 3-word types. You have to win a LOT on the 1-2 word types to overcome any regressions for 3-word types that no longer fit.

There is more than just the stdlib data types involved here. We’ve been advising performance-hungry Swift developers to tune their code to work well with 3-word inline buffers. If we drop it to 2 words, some fraction of user code will be impacted. We have no good way to know what that fraction would be.

Longer term, I think it would be really nice to be able to tune the buffer size for specific existential types where we have enough knowledge about conforming types and use cases to make that a sensible thing to do. Perhaps the optimizer could even tune the buffer size automatically when all possible conforming types are statically knowable.

I hope this future direction is being considered while making decisions about ABI.

That’s a good idea for potential internal optimizations, but I don’t think it affects ABI. IIUC, ABI would dictate the behavior surrounding public interfaces, which cannot see all use cases, and thus this optimization is never applicable.

The good news is that internal interfaces can always be optimized, de-virtualized, specialized, and have this sort of optimization applied. I don’t know how a theoretical multi-module optimization approach could pan out, but this might be an idea for that too.

One interesting question here is how would that work. Obviously you don’t want to copy from the inline buffer into a new heap object. I wonder if we could have a way to treat the box with the larger inline buffer as the heap pointer, preventing reallocation. Just a random thought.

That is a great idea. Do you know how to split an existing thread, or should I start new ones?

I don’t think you can split, but an admin might (@Nicole_Jacque ?) (don’t know if Discourse allows it at all). Otherwise, new threads with links to the originals would work.

I can split – let me test whether or not non-admins can too.

Ok, looks like it’s admin only. Do you want me to split this from Michael Gottesman’s post?

If possible, I’d say splitting the regex discussion into a thread and the raw string discussion into another. Then @Michael_Ilseman can create threads about the other topics mentioned, like missing API.

Ah, that looks a little complicated and it might be better to just spin off new threads. @Jon_Shier, do you think you have enough of an idea on what to do for Character properties to start a pitch on evolution? Alternatively, I could start a more open-ended preliminary discussion with some guidance.

More details of String’s ABI settle by the day, so it might make sense to continue that avenue of discussion in a new thread anyways. This is likely a prerequisite for the performance additions like a theoretical UnmanagedString and exposed performance flags anyways.

@anandabits has already started a discussion about the generalization of pattern matching at Generalized pattern matching. It might make sense to pile on there for that.

For regular expressions, there’s still a lot of syntactic holes in the straw-man. A new thread with a new straw-man to be knocked down is in order. As immediate focus is on ABI, it would be a slow-moving thread, but I think it would make sense to start in a week or two.

I do want to begin the discussion (perhaps on “development” at first) about the String interpolation performance issues. @beccadax, are you interested in starting that? Do you want any help or preliminary discussion prior?

In a few weeks, I’d like to solicit thoughts on a “String Dojo” in the Using Swift category.

I’m happy to take a stab at the UnicodeScalar/Character properties pitch based on my ICU bindings as well, if @Jon_Shier would like. (I haven’t had the time I wanted to put into a thoughtful opening post, and I still haven’t wedged Discourse into my daily workflow yet, but maybe a brief post to kick off discussion is still in order.)


Doh! I totally meant @allevato instead of @Jon_Shier ! (This certainly demonstrates the need for threading!).

@allevato, please proceed!

Finally had a chance to jot down a pitch—it can be found here.

I completely agree with @anandabits here. There is nothing in the ABI that seems like it would preclude adding the ability to say (making up syntax, which is obviously wrong):

var x : SomeExistentialType$32

and have it reserve space for 32 inline words of storage. This really does seem like the right long term answer: the Swift compiler should pick a right default size that is small (2 words would be great :-), and then allow specific authors to pick the existential size that makes sense for their app. This is often goodness because Swift programmers often have a good idea of what sorts of types will conform to their protocols, particularly if building an app or something else where there is a closed set of expected types that conform to a protocol.


I hadn’t been thinking of tuning the buffer for individual properties (although that might be useful as well). I was thinking of tuning the buffer size for all existential values of a specific protocol (or at least tuning the default if a property-level override was also supported).

Good point, that would also make a lot of sense.