Skip to content

add: throughput benchmark + docs for initial-load scenarios#23

Merged
viggy28 merged 2 commits into
mainfrom
local-benchmark
Apr 19, 2026
Merged

add: throughput benchmark + docs for initial-load scenarios#23
viggy28 merged 2 commits into
mainfrom
local-benchmark

Conversation

@viggy28

@viggy28 viggy28 commented Apr 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • New integration-test suite at test/integration/throughput_test.go that measures initial-load INSERT throughput (rows/sec landed in Iceberg) across multiple flush configs and transaction shapes.
  • Throughput is measured by tapping the writer's flush completed log via a custom slog.Handler — microsecond-accurate, zero MinIO contention, no polling lag. A comment at the log site in internal/iceberg/writer.go documents the dependency.
  • New documentation under docs/benchmarks/ with methodology, reproduction steps, hardware disclosure, explicit caveats, and a first results file (initial-load.md).

Headline findings (1M rows, localhost MinIO, Mac M3 Max, Docker Desktop)

Shape PG insert Sync RPS
bulk 2.28s 7.10s 140,766
batch 2.78s 6.06s 165,069
oltp 38.53s 6.05s 165,403
single 6m04s 14.03s 71,259

Notable: one giant transaction (bulk) is ~17% slower than 1,000-row transactions, stable across repeat runs. Small-but-not-tiny transactions (10–1,000 rows) are optimal.

Caveats baked into the docs

  • Localhost MinIO has sub-ms PUT latency; real S3 is 20–50ms per PUT. Numbers are an upper bound, not production.
  • Docker Desktop on macOS caps PG fsync at ~2.7K commits/sec; Linux + NVMe would be 4–10× faster on small-transaction inserts.
  • Streambed uses pgoutput proto_version '1' — no streaming of in-progress transactions. Noted as a known limitation.
  • Initial-load (WAL backlog drain), not steady-state CDC.

Test plan

  • docker compose -f test/integration/docker-compose.yml up -d --wait
  • go test -tags integration -v -timeout 1200s -run TestInsertThroughput ./test/integration/... passes
  • go test -tags integration -v -timeout 1200s -run TestInsertThroughputByShape ./test/integration/... passes
  • Existing integration tests still pass (no regressions in writer behavior from the added comment)
  • docs/benchmarks/README.md renders correctly on GitHub
  • docs/benchmarks/initial-load.md renders correctly on GitHub

🤖 Generated with Claude Code

viggy28 and others added 2 commits April 18, 2026 23:01
Introduces TestInsertThroughput and TestInsertThroughputByShape in
test/integration/throughput_test.go to measure how fast Streambed
drains a WAL backlog into Iceberg. Throughput is measured by tapping
the writer's "flush completed" log line via a custom slog.Handler,
which gives microsecond-accurate timing with no polling overhead.

A comment at the log site in internal/iceberg/writer.go flags the
log-format dependency so future changes to the log keys prompt a
corresponding update to the benchmark.

Also ignores .claude/ from the working tree.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
docs/benchmarks/README.md covers methodology (flush-log tapping rather
than Iceberg polling), reproduction steps, hardware disclosure, and
explicit caveats about localhost MinIO, Docker Desktop on macOS,
proto_version=1, initial-load vs steady-state, and single-run precision.

docs/benchmarks/initial-load.md captures results from a 1M-row run
across four transaction shapes (bulk / batch / oltp / single) on the
optimized flush config. Includes the finding that one-giant-transaction
("bulk") is ~17% slower than 1,000-row transactions at this scale, and
the expected 2.3x slowdown for pathological 1-row-per-commit workloads.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@viggy28
viggy28 merged commit 19947ae into main Apr 19, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant