Live data from Hacker News

How fast are Linux pipes anyway? (2022)

mazzo.li

21–30 of 116 posts

Re: How fast are Linux pipes anyway? (2022)

#22
post #4

One surprising fact about Linux pipes I stumbled across 4 years ago is that using a pipe can create indeterministic behavior: https://www.gibney.org/the_output_of_linux_pipes_can_be_inde...

That may have been surprising, but, if you think about it a little deeper, it makes perfect sense. Programs in a pipeline execute concurrently. If they didn’t, pipelines wouldn’t be useful. For instance a pipeline that downloads a tar file with curl and then untars it. If you wait for curl to finish before running tar, you run in to all sorts of problems. For instance, where do you store the intermediate tar file if it’s really large? Tar needs to run while curl is running to keep buffers small and make execution fast. The only control flow between pipeline programs is done via stdin and stdout. In your example program, you write to stderr so naturally that’s not part of the deterministic control flow.

Re: How fast are Linux pipes anyway? (2022)

#23
post #4

One surprising fact about Linux pipes I stumbled across 4 years ago is that using a pipe can create indeterministic behavior: https://www.gibney.org/the_output_of_linux_pipes_can_be_inde...

It that surprising? What would you have guessed output would look like, and why? Perhaps that information would help straighten out any confusion.

The command, perhaps intentionally, looks unusual (any code reviewer would certainly be scratching their head):

There's an "echo red" in there but it's never sent anywhere (perhaps a joke with "red herring"?).

There's an "echo green" sent to stderr, that will only be visible if it terminates before "echo blue".

The exact order would be dependent on output buffering, which will depend on which time slice is sorted first, which will vary with number of cpus and their respective load. So yes, it will be indeterministic, but in the same way "top" is.

Re: How fast are Linux pipes anyway? (2022)

#24

TL;DR: Maximum pipe speed, assuming both programs are written as optimally as possible, is approximately the speed of what one core in your system can read/write; this is because, essentially, the kernel maps the same physical memory page from one program's stdout to the other's stdin, thus making the operation a zerocopy (or a fast onecopy in slightly less optimal situations). I've known this one for awhile, and it…

I assume for heterogenous cores (power vs efficiency cores) it bottlenecks on the throughput of the slowest core?

Surprisingly no. I'd expect similar performance.

In these designs, the actual memory controller that talks to the RAM is part of an internal fabric, and the fabric link between the core and the memory controller is (technically) your upper limit.

For both Intel and AMD, the size of the fabric link remains constant to the expected performance of the different cores, as the theoretical usage/performance of the load/store units remain otherwise constant in relation, no matter if it is a big core or a little core.

Also, notice: the maximum performance of load-store units is your actual upper limit, period. Some CPUs historically never achieved their maximum theoretical performance because the units were never engaged optimally; sometimes this is because some ports on the load/store units are only accessible from certain instructions (often due to being reserved only for SIMD; this is why memcpy impls often use SSE/AVX, just to exploit this fact).

That said, load-store performance usually approaches that core's L2 theoretical maximum, which is greater than what any core generally can get out of its fabric link. Ergo, fabric link is often governing what you're seeing in situations like this.

On Intel and AMD's clusters, the memory controller serving their respective core cluster designs requires anywhere from 2 to 4 cores saturating their links to reach peak performance. Also, sibling threads on the same core will compete for access to that link, so it isn't merely threads that get you there, but actual core saturation.

On a dummy benchmark like proposed in the linked article, the performance of a single process being piped to another process, either in the situation of "both processes are actually on the same big core, simultaneously hyper-threading", or "two sibling little cores in the same core cluster, being serviced by the same memory controller", the upper limit of performance should approximate optimal usage of memory bandwidth, but in some cases on some architectures this will actually approximate L3 bandwidth (a higher value).

Also, as a side note: little cores aren't little. For a little bit more silicon usage, and a little bit less power usage, two little cores approximate one big core /w two threads optimally executing, even in Intel's surprisingly optimal small core design, but very much true in Zen4c. As in, I could buy a "whoops, all little cores" CPU of sufficient size for my desktop, and still be happy (or, possibly, even happier).

Re: How fast are Linux pipes anyway? (2022)

#25

TL;DR: Maximum pipe speed, assuming both programs are written as optimally as possible, is approximately the speed of what one core in your system can read/write; this is because, essentially, the kernel maps the same physical memory page from one program's stdout to the other's stdin, thus making the operation a zerocopy (or a fast onecopy in slightly less optimal situations). I've known this one for awhile, and it…

This is magic system stuff I don’t understand, does it have to go all the way up to the memory or will the caches save us from that trip?

Depends entirely on the CPU architecture.

The most simple answer I can give is: yes, when its safe; when its not safe, that's part of an entire category of meltdown/spectre family exploits.

Re: How fast are Linux pipes anyway? (2022)

#26
post #4

One surprising fact about Linux pipes I stumbled across 4 years ago is that using a pipe can create indeterministic behavior: https://www.gibney.org/the_output_of_linux_pipes_can_be_inde...

Chatgpt was able to figure this out with a simple "what does the following do". But it could also be a case of chatgpt being trained on your article.

>>> Note: The ordering of "green" and "blue" in the output might vary because these streams (stdout and stderr) might be buffered differently by the shell or operating system. Most commonly, you will see the output as illustrated above.

Re: How fast are Linux pipes anyway? (2022)

#28

TL;DR: Maximum pipe speed, assuming both programs are written as optimally as possible, is approximately the speed of what one core in your system can read/write; this is because, essentially, the kernel maps the same physical memory page from one program's stdout to the other's stdin, thus making the operation a zerocopy (or a fast onecopy in slightly less optimal situations). I've known this one for awhile, and it…

This is why threads aren't nearly as important as many programmers seem to think. Chances are, whatever application you're building can be done in a cleaner way using pipes + processes or green/user-space threads depending on the workload in question. It can be less convenient , but message passing is usually preferable to deadlock hell.

> This is why threads aren't nearly as important as many programmers seem to think. Chances are, whatever application you're building can be done in a cleaner way using pipes + processes or green/user-space threads depending on the workload in question.

I think you're making wild claims based on putting up your overgeneralized strawman (i.e., "threads aren't nearly as important as many programmers seem to think") that afterwards you try to water down with weasel words ("depending on the workload in question").

Threads are widely used because they bring most of the benefits of processes (concurrent control flow, and in multicore processors also performance) without the constraints and limitations they bring (exclusive memory space, slow creation, performance penalty caused by serialization in IPC, awkward API, etc).

In multithreaded apps, to get threads to communicate between each other all you need to do to is point to the memory address of the object you instantiated. No serialization needed, no nothing. You simply cannot beat this in terms of "clean way" of doing things.

> It can be less convenient, but (...)

That's quite the euphemism, and overlooks why threads are largely preferred.

Re: How fast are Linux pipes anyway? (2022)

#30
Are there good data handling libraries that provide abstractions over pipes, sockets, files, and memory and implement optimizations like these? I'd be interested in knowing if there are such libraries in C, C++, Rust, or other systems languages.

I wasn't familiar with some of the APIs mentioned in the article like splice() and vmsplice(), so I wondered if there are libraries that I might use when building ~low-level applications that take advantage of these and related optimizations where possible automagically. (As another commenter mentioned: these APIs are hard to use and most programs don't take advantage of them)

Do libraries like libuv, tokio, Netty handle this automatically on Linux? (From some brief research, it seems like probably they do)

Post reply on HN