Skip to content

Benchmarks

These numbers measure the pool alone: a job is an int and the workers do nothing with it, so what’s left is the cost of queueing a job and handing it to a worker. Your jobs will dominate a real run; the point is that the pool adds as little as possible.

Delegate alone runs into a queue with room for every job. A job through workers runs through a queue of 1024: when the workers fall behind, Delegate waits, so the time per job is the pace of the whole pool. With 16 callers at once, the time is wall time per call across all of them, so it measures throughput.

Both versions ran on the same harness, with the same jobs.

Time per job, from Delegate to the worker, lower is better
Show as a table
Time per job, from Delegate to the worker: time and allocations, v2 against v3
Scenariov2v3
1 worker215.9 ns2 allocs38.8 ns0 allocs
16 workers412.1 ns2 allocs110.1 ns0 allocs
1 worker, 16 callers at once372.3 ns2 allocs86.9 ns0 allocs
16 workers, 16 callers at once258.3 ns2 allocs55.4 ns0 allocs

Apple M4 Max, Go 1.27.0, median of 5 runs.

v2 built a slice of reflect.Values for every job, boxing each argument, and called the worker with reflect.Value.Call. v3 sends the job on a typed channel and calls the worker’s func directly.

With jobs that do nothing, one caller can’t keep 16 workers busy: they wait and wake for every job, which costs more than the job itself. With real work, the workers stay busy and take jobs straight from the queue.

BenchmarkTimeMemoryAllocations
DelegateInto a queue with room, no worker11.0 ns0 B0
Job/workers=1One caller, one worker, a queue of 102438.0 ns0 B0
Job/workers=16One caller, sixteen workers104.1 ns0 B0
JobParallelSixteen callers, sixteen workers46.2 ns0 B0

From a clone of the repository:

Terminal window
go test -run '^$' -bench . -benchmem

To compare two versions, run each a few times and compare with benchstat:

Terminal window
go test -run '^$' -bench . -count 10 > new.txt
benchstat old.txt new.txt

The allocation counts are also enforced by tests: TestAllocations fails if a call allocates more than it should.