Some years later this got revisited due to needing to use the same thing under C# on Win10 and while it was better it was still a major embarrassment how big the performance gap was.
When you say the performance was hideous, are you referring to I/O after the pipe is already connected/open, or before? The former would he surprising, but the latter not - opening and closing a ton of pipes is not something you'd expect an OS to be optimized for - and it would be somewhat surprising if your use case requires the latter.
And yeah, that seems more or less what I expected. The implementation is probably optimized for repeated I/O on established connections, not repeated unestablished ones. Which would be similar to filesystem I/O on Windows in that way - it's optimized for I/O on open files (especially larger ones), not for repeatedly opening and closing files (especially small ones). It makes me wonder what kinds of use cases require repeated connections on named pipes.
If the performance is comparable to Linux's after the connection, then I think that's important to note - since that's what matters to a lot of applications.
I would intuitively expect throughout (once all clients have connected) to be similar to on Linux, unless the Linux side uses syscalls like vmsplice() - but not sure, I've never tried benchmarking.
[0] https://learn.microsoft.com/en-us/windows/win32/api/winbase/...
They literally provided the registry to solve this very problem from the days of 16-bit Windows. Holding it against them in 2025 when they have given you a perfectly good alternative for decades is rather ridiculous and is evidence for the exact opposite of what you intended.
INI files are 100% different than the Registry. I rather have an configuration file over registry entries because the registry is just another kluge of bad design. Configuration files are text files that are well defined.
Example would be the registry settings to mark a URL that it needs to run in IE compatibility mode because the source use old IE features that are now obsolete and don't even work in Edge or a modern browser. It should of just been a simple string array.
[0] https://www.nexusmods.com/skyrimspecialedition/mods/18860
It's worth noting that in Win32, an unnamed pipe is just a named pipe with the name discarded. So this "3x faster" is, I think, the exact comparison we're interested in.
Not claiming that POSIX should or could attempt to address performance.
splice() is great when transferring data between pipes and UNIX sockets with zero-copy, but it is Linux-only.
splice() is the fastest and most efficient way to transfer data through pipes (on Linux), especially for large volumes. It bypasses memory allocations in userspace (as opposed to read(v)/write(v)), there is no extra buffer management logic, there is no memcpy() or iovec traversal.
Sadly on BSDs, for pipes, readv() / writev() is the most performant way to achieve the same if I am not mistaken. Please correct me if I am wrong.
At any rate, this is a great article.
On Linux, sendfile supports more than just file to socket, as it's implemented using splice. I've used it for file-to-block-device in the past.
Proper use of io_uring should finally have it beat or at least matched.
https://news.ycombinator.com/item?id=31592934 (200 comments)
https://news.ycombinator.com/item?id=37782493 (105 comments)
I'd like to use splice more, but the end of the article talked about the security implications and some ABI breaking.
I'm curious to know if long term plans are to keep splice around?
I'd also be curious how hard it would be to patch the default pipe to always use splice for performance improvements.
https://en.m.wikipedia.org/wiki/Doors_(computing)
Look for Doors solaris and there are quite a few articles.