Linux pipe(2) vs ring buffer
I decided a few days ago to finally rework the architecture of my music player (the C part) and one of the tasks I instinctively outlined is to replace the mechanism used to stream bytes between the decoder and libao submission threads.
To be more explicit, what I need is a single producer, single consumer (SPSC) fixed size
blocking FIFO queue. Opting for pipe
was a very natural solution,
then, even if it's something meant for inter-process communication.
But this implies a lot more memory copying around than something exploiting threads' shared
memory. So I wrote a basic ring buffer guarded by condition variables (as a macro "template")
containing struct {void *ptr; size_t len;}
and a memory pool to feed it.
I could have opted for the mmap trick or a bip buffer but decided that a more general purpose queue for all kind of message passing between threads would serve me better in the long run.
Here is the code comparing pipes with the ring buffer via a simple test program spawning two threads, T1 reading from stdin, sending the data to T2 which then writes it to stdout. And here are the results (in seconds) of transferring a 400 MB file through them using 4 different block sizes (in bytes):
Substantial gains, but it's not like consumer audio needs massive bandwidth. I'll probably put it at the bottom of the to-do list.