pulse — Benchmarks
Load measurements of the SKIP-LOCKED batch-dispatch design.
Environment
| Machine | Intel i7-10870H (16 threads), 23 GiB RAM — everything on one host |
| Stack | Go 1.26 · PostgreSQL 16 (default config) · loopback gRPC |
| Server | one pulsed (dispatch tick 500ms, claim batch 100) |
| Handler | no-op (measures pulse, not work) |
Methodology
cmd/loadgen starts --streams worker connections (each is one
server-side dispatcher loop) with --concurrency 20 handlers per stream, then submits
--jobs jobs from 8 concurrent producers. The submit timestamp travels inside the payload,
so dispatch latency (submit → handler start) is measured on a single clock. With --db,
the pg_stat_database commit/rollback deltas over the run are reported.
DB_HOST=postgres://…/pulse_test go run ./cmd/pulsed # terminal 1
go run ./cmd/loadgen --jobs 2000 --streams 8 --db postgres://…/pulse_testResults
2,000 jobs, 8 workers (2026-07-04):
| metric | value |
|---|---|
| submit rate | 4,169 jobs/s |
| end-to-end throughput | 1,223 jobs/s |
| dispatch p50 / p95 | 773ms / 1.18s |
| aborted transactions (claim conflicts) | 0 |
| DB transactions per job | ~1.6 |
Pending runs
- Worker sweep (1/2/8/16/32 streams) — expected: throughput scales with workers until Postgres saturates, conflicts stay 0.
- Deep-backlog run (500k+ pre-loaded) — expected: flat drain rate, no death spiral.
- Multi-instance (
pulsed× 2) sweep. - Schedule-fire latency and throughput (
At(now+2s)× N — fire-to-handler measured against the known due time).
Caveats
- Single host, loopback, default Postgres config, no-op handler: figures isolate dispatch machinery, not real workloads.
- Single run per configuration; individual figures vary ±10%.