ipc-bench: measuring the ping-pong latency of pipes, Unix sockets, TCP and io_uring
Latency benchmarks of Unix IPC mechanisms
At a glance
- What is it?
- ipc-bench is a small set of C programs that measure the round-trip latency and throughput of Unix IPC mechanisms on your own machine, covering pipes, Unix domain sockets, TCP sockets, eventfd and io_uring MSG_RING where available. It suits a systems programmer who needs a number for their own hardware rather than a published figure.
- Who is it for?
- ipc-bench fits a systems programmer who has to choose an IPC mechanism and wants the round-trip numbers measured on the target machine rather than read from a paper, and it does not fit a reader looking for a framework or a library, since the repository contains benchmarks and nothing else.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 19 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the benchmark set actually covers
ipc-bench is described in one line as some very crude IPC benchmarks, and the word crude is the author's own. It is a set of standalone C executables, not a library, and the top-level repository layout is minimal: a CMakeLists.txt, a LICENSE, the README and a src directory.
The measurements come in two families, and the split is what defines the tool.
The ping-pong latency benchmarks cover pipes, Unix domain sockets, TCP sockets, eventfd, which is Linux only and used for notifications, and io_uring MSG_RING, also Linux only and used for ring-to-ring messages. Ping-pong here means a round trip: one process writes, the other reads and writes back, and the clock stops when the reply comes back. That is the number that matters for request-response protocols, and it is a different quantity from one-way throughput.
The throughput benchmarks cover three of the same mechanisms: pipes, Unix domain sockets and TCP sockets. So eventfd and io_uring are latency only, which makes sense, since neither is a byte stream. Both mechanisms are Linux kernel features that do not exist on macOS or BSD, and the README marks them with a Linux only note rather than pretending they are portable.
The primary language is C, the licence is MIT, the default branch is master, and the last push was on 2026-10-04. The repository has no GitHub releases, so there is no tagged version to pin: you build whatever is on the default branch.
The point of the tool is worth stating plainly. It exists so that a developer on a particular machine, kernel and CPU can get a number for that setup, rather than a number from someone else's machine.
Building with CMake, and the optional liburing dependency
The build requirements are modest: a C compiler, CMake 3.10 or newer, and a build tool such as Make or Ninja. On Linux there is an optional extra step, which is to install the optional liburing development package, version 2.2 or newer, and pkg-config, so that the io_uring_lat executable is also built.
That optionality is worth understanding rather than skipping. Without liburing the project still builds and every other benchmark still runs, and io_uring_lat simply does not exist. So a reader on Linux who wants the io_uring number has to notice the dependency rather than discover a missing binary.
The build itself is three commands from the repository root.
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .The out-of-source build directory is standard CMake practice, and the Release build type matters here in a way it rarely does for a tool that only prints numbers. A benchmark compiled without optimisation measures the benchmark harness rather than the IPC mechanism, and the resulting figure would be a property of the compiler flags instead of of the kernel.
Executables are created in the build directory, so the tools are run from there, which is also why every example path in the README begins with a dot slash. The tools take their parameters on the command line rather than through a config file, and the argument convention is consistent: a message size in bytes and a number of iterations.
The CI badge in the README points at a GitHub Actions workflow for C and C++, and the credit line names one contributor, desbma, for adding cross platform support for clock_gettime. That detail explains why the benchmarks can run outside Linux at all, since clock_gettime with a monotonic source is what a latency measurement needs and its availability was historically uneven.
Running the benchmarks, and what the numbers mean
The example given is the pipe latency measurement with 8-byte messages and 100,000 roundtrips, run from the build directory.
./pipe_lat 8 100000Two arguments, both meaningful. The message size sets the payload, and the iteration count sets how many round trips are averaged, which is what makes the figure stable enough to compare between mechanisms. A single round trip would measure scheduler noise more than transport cost.
On Linux two more executables are available.
./eventfd_lat 100000
./io_uring_lat 100000 # if built with liburingNotice the difference in arguments. eventfd_lat and io_uring_lat take only the iteration count, because neither carries a byte payload: eventfd is a counter that signals an event, and io_uring MSG_RING moves fixed-size descriptors between rings rather than bytes through a stream. The pipe benchmark needs a size argument because pipes carry data.
The comment on the io_uring line, if built with liburing, is not incidental. It records the conditional nature of that binary, and it is the reminder that a missing executable is a build configuration outcome rather than a failure of the tool.
There is no mention anywhere in the README of the throughput executables being invoked, and their names are not given either, so the exact command line for the throughput side is not documented in the repository readme. What is documented is the shape of the latency side, and the throughput tools are named in the README's own list of what is covered.
The measurement methodology itself is not described in detail in the readme: it does not state the clock source used, the process scheduling arrangement, or how the result is summarised. The credit to desbma for cross platform clock_gettime support is the only indication that a monotonic clock is involved. If the numbers matter for a decision, running them is the only way to know what was measured.
Why these mechanisms, and what the list is missing
The six latency targets are not arbitrary, and looking at them as a group tells you what kind of problem this was built to answer.
Pipes are the baseline that every Unix programmer reaches for first, and they are anonymous and unidirectional. Unix domain sockets are the answer when you need a bidirectional connection with a filesystem path, which is what makes them the default for local RPC. TCP sockets are included deliberately, and they are the interesting comparison: a TCP socket over loopback goes through the TCP stack, so the gap between Unix domain socket latency and TCP socket latency is the cost of that stack, measured on your machine rather than estimated.
The two Linux-only entries are the interesting ones. eventfd is a lightweight notification primitive, included because a notification is often all that a signalling path needs, and it is much cheaper than a pipe write. io_uring MSG_RING is a ring-to-ring message passing mechanism, and it is the newest thing in the list, included because the point of a benchmark set is to have something recent to compare against the classics.
What the list does not contain is as informative as what it does. There is no shared memory segment benchmark, no POSIX message queue, no socketpair, no SignalFired or eventfd with epoll for the notification path. That is not a claim that those are worse, it is a statement about scope: these are the mechanisms a particular developer reached for in a particular project, and the tool measures them so the choice can be made on numbers.
The consequence for a reader is that a missing mechanism is not evidence against it. If your design needs shared memory, this repository does not answer your question, and you would need to write the comparison yourself.
What this is for, and when a different tool is the right call
Three limitations are worth naming, and they are the difference between a measurement tool and a platform.
The first is that the numbers are only as good as the environment. These are latency benchmarks run on the machine you run them on, so CPU frequency scaling, the scheduler, the NUMA layout of the machine, the kernel version and the C library all move the result. A figure quoted from a blog post is a fact about that author's hardware, and the value of this repository is that it lets you produce a figure about yours instead. There is also no attempt here to isolate any variable, and no statistical treatment of the samples beyond what the tool computes.
The second is that the benchmarks do not model an application. A ping-pong measures one message at a time with the other side blocked and waiting. It says nothing about throughput under concurrent load, about scheduling fairness with several clients, or about how a mechanism behaves when buffers fill. The throughput executables exist in the repository, but the readme does not document how to invoke them or what shape their output takes, so the one-sided throughput case is less served than the latency case.
The third is platform coverage. Two of the six latency targets exist only on Linux, and the project has no GitHub releases and no version history to consult, so you are building from the tip of the default branch.
The alternative for a reader who needs more is a general system benchmarking suite, which offers throughput, latency and CPU and memory profiling together and ships more carefully engineered harnesses. The difference in approach is the point. A general suite wants to be a measurement instrument; ipc-bench wants to answer one question quickly, in C, on your machine, with six mechanisms and no ceremony. If your decision is which of pipes, Unix domain sockets, TCP, eventfd or io_uring to use on a specific machine, this is the narrower and more direct instrument for it.
Editorial conclusion
ipc-bench fits a systems programmer who has to choose an IPC mechanism and wants the round-trip numbers measured on the target machine rather than read from a paper, and it does not fit a reader looking for a framework or a library, since the repository contains benchmarks and nothing else. Before quoting any figure it prints, run it on the hardware and kernel you actually intend to deploy on, and on Linux install the optional liburing package and pkg-config so the io_uring_lat executable is built at all.
Frequently asked questions
What does ipc-bench measure?
It measures ping-pong latency for pipes, Unix domain sockets, TCP sockets, eventfd and io_uring MSG_RING, and throughput for pipes, Unix domain sockets and TCP sockets. The eventfd and io_uring benchmarks are Linux only.
How do I build ipc-bench?
You need a C compiler, CMake 3.10 or newer and a build tool such as Make or Ninja. From the repository root run mkdir -p build, cd build, cmake -DCMAKE_BUILD_TYPE=Release .. and cmake --build ., and the executables end up in the build directory.
How do I run a pipe latency benchmark?
From the build directory, run ./pipe_lat 8 100000, where the first argument is the message size in bytes and the second is the number of roundtrips. The Linux-only benchmarks are run as ./eventfd_lat 100000 and ./io_uring_lat 100000, the latter only if liburing was installed.
Why is liburing optional in ipc-bench?
The optional liburing development package, version 2.2 or newer, plus pkg-config is only needed to also build io_uring_lat on Linux. Without it the project still builds and every other benchmark still runs, and the io_uring executable simply does not exist.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rigtorp-ipc-bench)Was this useful?