Both pools built from source and measured on the same server hardware, one pool at a time, pointed at the same backend, driven by the same load, with correctness checked before any number is trusted.
Measured 24 July 2026. Every figure below is reproducible from the harness in this repository.
mkpool validates a share about 14% faster mkpool sustains up to 1.26x the throughput at high load
This is a case study, not a callout. ckpool is a mature, battle tested Stratum server that has run real Bitcoin mining infrastructure for years, and its lean C design sets a genuinely high bar. This comparison exists to understand honestly where mkpool stands against that bar and to learn from it, not to disparage ckpool or the people who built it. It is published openly and reproducibly, in the same spirit ckpool itself is, so anyone can re-run it and check the numbers. Where ckpool is faster, this report says so plainly.
| Role | Machine |
|---|---|
| Pool under test (the measured machine) | AMD EPYC 9V45, 64 vCPUs, 125 GiB RAM |
| Load generator (separate machine) | AMD EPYC 9V74, 64 vCPUs, 251 GiB RAM |
| Operating system | Ubuntu 24.04.4 LTS, Linux 6.17 |
| Bitcoin node | Bitcoin Core 27.1.0 |
| mkpool | version 0.4.0, built -O3 -flto -march=native |
| ckpool | current release, commit 308410d |
There are two kinds of measurement here, and they answer two different questions.
The first is the cost of validating a single share in isolation, timed on one CPU core against a real Bitcoin mainnet block. This is the pool's core work and it sets how much a single core can handle.
The second is how the running server behaves under load: how many shares per second it validates across a range of connected miners, how quickly it answers, how many connections it holds and at what memory cost, and how fast it accepts reconnecting miners. For this, each pool ran as a live server on the pool machine and was driven by the load generator on the second machine over the network. To keep it honest, the node's block template was served at a real mainnet difficulty, so every submitted share was fully validated by both pools but never trivially counted as a block. The template carried a realistic set of transactions, so the coinbase and merkle work per share matched real conditions. Each measurement was repeated three times and averaged, with each pool run one at a time on the same machine against the same backend.
Rebuild the coinbase, fold it through the merkle branch, assemble the 80 byte header, hash it twice with SHA-256, and compare to target. We timed this three million times, pinned to one core, on real Bitcoin mainnet block 959,143 with its full transaction set and genuine 12 level merkle branch. Before any timing, both sides reproduce that block's published merkle root, so both are proven to be doing the full, correct work.
| Pool | Time per share | Shares per second, per core |
|---|---|---|
| mkpool | 1,818 ns | 550,000 |
ckpool, its own release flags (-O2 -msse4.1 -msha) | 2,065 ns | 484,000 |
ckpool, matched flags (-O3 -march=native) | 2,223 ns | 450,000 |
mkpool validates a share about 14% faster than ckpool built the way ckpool ships, and about 22% faster when both are compiled with identical flags. Both do this with zero memory allocations per share, so the difference is in the validation code itself, not framework overhead.
With the server live and miners connected, how many shares per second does each pool fully validate? We swept the number of connections from 128 up to 2,048 and measured the sustained validated-share rate at each level.
| Connected miners | mkpool | ckpool | Faster pool |
|---|---|---|---|
| 128 | 25,418 | 28,569 | ckpool, 1.12x |
| 256 | 61,722 | 54,868 | mkpool, 1.12x |
| 512 | 81,347 | 93,809 | ckpool, 1.15x |
| 1024 | 117,481 | 92,980 | mkpool, 1.26x |
| 2048 | 103,426 | 92,606 | mkpool, 1.12x |
ckpool holds a small lead at the lowest connection counts, but its throughput flattens near 93,000 shares per second from 512 connections upward. mkpool keeps climbing, reaching 117,000 shares per second at 1,024 connections, about 1.26x ckpool, and stays ahead at 2,048. In other words, mkpool scales better into the connection counts a busy pool actually sees.
The remaining measurements are close, and worth stating plainly.
Under a fixed, steady load both pools answer in essentially the same time. This is a tie.
| Pool | p50 | p90 | p99 |
|---|---|---|---|
| mkpool | 66.2 ms | 66.3 ms | 66.9 ms |
| ckpool | 66.6 ms | 66.7 ms | 67.3 ms |
Both pools held all 8,000 requested connections without dropping any. ckpool carries a lighter memory footprint per connection.
| Pool | Connections held | Pool memory | Per connection |
|---|---|---|---|
| mkpool | 8,000 | 116 MiB | 14.9 KiB |
| ckpool | 8,000 | 84 MiB | 10.8 KiB |
Rate of full connect, subscribe, authorize, and disconnect cycles the server accepts per second. ckpool is a little quicker here.
| Pool | Reconnections per second |
|---|---|
| mkpool | 676 |
| ckpool | 766 |
| Measurement | Result |
|---|---|
| Per-share validation speed | mkpool, about 14 to 22% faster |
| Request throughput at high load | mkpool, up to 1.26x at 1,024 connections |
| Submit to acknowledge latency | tie, about 66 ms both |
| Connection capacity | tie, both held 8,000 |
| Memory per connection | ckpool, about 28% lighter |
| Reconnection handling | ckpool, about 13% faster |
mkpool wins the two measurements that most define a pool's capacity: how fast it validates a share, and how many shares per second it sustains as the miner count grows. ckpool keeps a modest edge on memory footprint and on the rate of reconnecting sessions. Latency and raw connection capacity are level.
The per-share validation benchmark is a single command:
MKPOOL=/path/to/mkpool CKPOOL=/path/to/ckpool CORE=3 ITERS=3000000 bash microbench/compare.shIt builds and runs both pools' validation code on the same core against real block 959143 and refuses to print a number unless both reproduce the block's published merkle root. For the server measurements, one machine runs the pool and a second runs the load generator; both pools are fed the same node template at mainnet difficulty and driven with the same connection sweep. Full configurations for both pools, and the raw per-run data behind every figure here, are published alongside this report.
ckpool is built from its canonical repository at its release defaults; mkpool at its own Release flags. Numbers vary by processor. Re-run it on your own hardware and treat anything that does not reproduce as wrong.