Circular Buffer

Hi @kitaisreal,

Thanks for looking into this!

A circular buffer is definitely something that the standard library needs, as it's a good foundation for many other data structures. It should be the first of several data structures that belong in the standard library, since as you mention it would be useful in the implementation of the standard library itself.

That said, I think we need a slightly different approach to the development of data structures to the one we've traditionally had with new algorithms when proposing additions to the standard library. Specifically, they need a more detailed design phase before moving to pitch, probably as a stand-alone package. The prototype needs to be coupled with a design document outlining exactly how the implementation will be achieved, and the design trade-offs made. Discussion of the design should probably happen elsewhere to the evolution pitches forum topic (possibly the Standard Library developer topic, or maybe on GitHub).

A big reason for this is the way data structures stabilize their ABI, and how this is very different to how algorithms do so. Since the standard library is ABI-stable, any additions will need care taken in stabilizing their ABI.

Right now, unless you want to keep your data structure as resilient, then implementing an ABI-stable data structure is a bit of a dark art. You need to spend a lot of time thinking about which parts of your data structure are going to be frozen and which aren't, and which methods should be inlinable and touch those frozen internals. This means spending time trading off future enhancements for performance today. It also involves trade-offs around of the user's binary – sometimes if you inline too much it has really bad consequences for code size.

Very little of this is currently documented because the techniques needed are still emerging – the engineers who work on the standard library have only been doing it in an ABI-stable context for the past year. Hopefully the design of new data structures will be an opportunity for those engineers to share what they've learned with the rest of the community.

A package by contrast has none of these problems (at least until we start distributing binary packages). They are never ABI stable and get shipped with the user's binary (just like the standard library used to). This gives you a lot more freedom to iterate, even after you release a 1.0 you can stand behind people using. By contrast, you may only get one shot to ever ship a version in the standard library, because performance for a type like this is critical so enough of it gets marked fragile (@frozen, @inlinable etc) in the first version that you can never change it later.

For these reasons, I'd recommend iterating on some possible implementations before moving to the pitch and PR against the standard library phase. Ideally this would start from a battle-tested base like the one found in NIO. It should also demonstrate performance where possible versus equivalent types in the standard library. For example, appending to a circular buffer could be benchmarked versus appending to Swift's array type.

Hope this helps and I or some of the other engineers who've worked on this would happy to go into more detail about any of this if needed.

Cheers,
Ben

18 Likes