From 47b792a9467556dada73aba1d96fb66dc8cc63d1 Mon Sep 17 00:00:00 2001 From: Nikita Aleksandrov Date: Tue, 7 Apr 2026 02:06:20 +0300 Subject: [PATCH 1/5] performance articles --- blog/2026-04-07-noop-drivers/index.md | 69 +++++++++ .../e2e_throughput.gnu | 29 ++++ .../e2e_throughput.png | Bin 0 -> 48764 bytes blog/2026-04-08-stroppy-perf/index.md | 136 ++++++++++++++++++ blog/2026-04-08-stroppy-perf/load_speedup.gnu | 31 ++++ blog/2026-04-08-stroppy-perf/load_speedup.png | Bin 0 -> 43700 bytes blog/2026-04-08-stroppy-perf/micro_ns.gnu | 29 ++++ blog/2026-04-08-stroppy-perf/micro_ns.png | Bin 0 -> 61642 bytes 8 files changed, 294 insertions(+) create mode 100644 blog/2026-04-07-noop-drivers/index.md create mode 100644 blog/2026-04-08-stroppy-perf/e2e_throughput.gnu create mode 100644 blog/2026-04-08-stroppy-perf/e2e_throughput.png create mode 100644 blog/2026-04-08-stroppy-perf/index.md create mode 100644 blog/2026-04-08-stroppy-perf/load_speedup.gnu create mode 100644 blog/2026-04-08-stroppy-perf/load_speedup.png create mode 100644 blog/2026-04-08-stroppy-perf/micro_ns.gnu create mode 100644 blog/2026-04-08-stroppy-perf/micro_ns.png diff --git a/blog/2026-04-07-noop-drivers/index.md b/blog/2026-04-07-noop-drivers/index.md new file mode 100644 index 0000000..5cca332 --- /dev/null +++ b/blog/2026-04-07-noop-drivers/index.md @@ -0,0 +1,69 @@ +--- +slug: measuring-stroppy-before-measuring-databases +title: "Measuring Stroppy Before Measuring Databases" +authors: [stroppy-authors] +tags: [development, drivers, noop, pg-noop, internals] +--- + +When you run a database benchmark, the tool itself is in the picture. If stroppy can only push 12 000 transactions per second, no database will ever look faster than that in your results — not because the database is slow, but because stroppy ran out of steam first. Knowing that ceiling matters. + +We added two noop layers to make that ceiling easy to find: one in-process (a dummy driver) and one over the wire (a standalone pg-noop server). Together they bracket stroppy's throughput with and without the PostgreSQL protocol stack in the way. + + + +## The Built-in Noop Driver + +The first layer is a driver inside stroppy that accepts all operations and discards them. The data generator runs in full, queries are built and parameterized correctly, but nothing reaches a socket. It landed in [PR #61](https://github.com/stroppy-io/stroppy/pull/61). + +It serves two purposes. During development, it gives us a full E2E path without requiring a database — useful for testing workload scripts and driver logic before spinning anything up. And during benchmarking, it measures stroppy's absolute throughput ceiling: the full stroppy cost with no network and no database in the picture. + +Running the TPC-C `pick` workload against the noop driver on our test machine: + +```bash +stroppy run tpcc/pick -d noop -- --vus 8 --duration 30s +``` + +gives about **100 000 iterations/s** at 8 VUs. That's the maximum stroppy can produce on this hardware. If we saw a real database approach this number, we'd know the database isn't the bottleneck — stroppy is. + +## pg-noop: Adding the Protocol Layer + +The second layer is a standalone server: [pg-noop](https://github.com/stroppy-io/pg-noop). It listens on a regular PostgreSQL port and speaks the full wire protocol — simple query, extended query, COPY — but treats every statement as a no-op and returns mechanically valid empty responses. + +```bash +# Install and run +curl -LsSf https://github.com/stroppy-io/pg-noop/releases/latest/download/pg-noop-installer.sh | sh +pgnoop + +# Run stroppy against it as a regular postgres target +stroppy run tpcc/pick -- --vus 8 --duration 30s +``` + +No configuration needed on stroppy's side — it connects to localhost:5432 and sees a normal PostgreSQL server. + +The implementation is small. It's built on the Rust [pgwire](https://github.com/sunng87/pgwire) library: a `NoopHandler` that implements the four required traits (`StartupHandler`, `SimpleQueryHandler`, `ExtendedQueryHandler`, `CopyHandler`), a Tokio acceptor loop, and jemalloc for the musl build. That's the whole thing. + +The same workload against pg-noop yields about **41 000 iterations/s** at VUS=8 — versus 100 000 against the in-process noop. The gap is the PostgreSQL wire protocol overhead on localhost: connection management, query serialization, network round-trips, response parsing. At VUS=1 the uncontended per-transaction cost difference is about 51 µs — the protocol cost with no database work. + +| Driver | VUS=1 | VUS=8 | +|--------|------:|------:| +| noop (in-process) | 29 421/s | 100 419/s | +| pg-noop (TCP localhost) | 11 814/s | 41 352/s | + +## What These Numbers Tell You + +Before comparing databases, you have two useful data points: + +- **Noop ceiling**: the hard upper bound on stroppy's throughput on this hardware. Any result near this number means stroppy might be the bottleneck. +- **pg-noop ceiling**: the upper bound when the full protocol stack is involved. Any result near this number means the database is doing very little work and the cost is mostly in the client. + +If your production PostgreSQL throughput sits well below the pg-noop ceiling, you're in good shape — the database is being measured, not the tool. If it's close, it's worth investigating whether stroppy is the limiting factor. + +These baselines are also useful for cross-machine comparisons: the noop and pg-noop numbers characterize the test machine itself, which helps when moving between hardware or comparing results across environments. + +--- + +Writing your own driver for a different database follows the same pattern as the noop driver — see [Extensibility](/docs/extensibility) for a walkthrough. + +--- + +That 100 000 iter/s ceiling didn't start there. The [next post](/blog/stroppy-generator-performance) covers the pprof sessions on stroppy itself and the generator-pipeline changes behind the numbers you just saw. diff --git a/blog/2026-04-08-stroppy-perf/e2e_throughput.gnu b/blog/2026-04-08-stroppy-perf/e2e_throughput.gnu new file mode 100644 index 0000000..6d6e0ef --- /dev/null +++ b/blog/2026-04-08-stroppy-perf/e2e_throughput.gnu @@ -0,0 +1,29 @@ +set terminal pngcairo size 1800,960 enhanced font "Sans,12" fontscale 2 linewidth 2 +set output "e2e_throughput.png" + +set style data histogram +set style histogram clustered gap 1 +set style fill solid 0.85 border -1 +set boxwidth 0.8 + +set title "tpcc/pick throughput — noop driver (median of 3×30s runs)" font "Sans,13" +set xlabel "Virtual Users" +set ylabel "Iterations / second" +set yrange [0:130000] +set format y "%'.0f" +set grid y lt 0 lc "grey" lw 0.5 +set key top left + +set xtics ("1" 0, "2" 1, "4" 2, "8" 3, "16" 4) + +# before, after +$data << EOD +"1" 25424 29421 +"2" 43175 50072 +"4" 65919 74566 +"8" 90264 100419 +"16" 100170 111489 +EOD + +plot $data using 2:xtic(1) title "before" lc rgb "#5778a4", \ + $data using 3 title "after" lc rgb "#e49444" diff --git a/blog/2026-04-08-stroppy-perf/e2e_throughput.png b/blog/2026-04-08-stroppy-perf/e2e_throughput.png new file mode 100644 index 0000000000000000000000000000000000000000..39cd6cc5506b79a8650e17df1de8ff95435bd0ab GIT binary patch literal 48764 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

u>qAvfcYMJAhHRpC3dgM3>pAam!m@7-P(vH&B8g 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 + +## What pprof Showed + +To profile, we run stroppy with `--profiling-enabled` and pull a profile against the built-in pprof endpoint: + +```bash +stroppy run tpcc/pick -d noop -- --vus 8 --duration 10m --profiling-enabled +# in another terminal: +go tool pprof -http=:8080 http://localhost:6565/debug/pprof/profile?seconds=30 +``` + +Three things stood out in the CPU and heap profiles: + +1. **`WordCutter.Cut`** — every generated string copied its buffer via `strings.Builder.String()`. One 16-byte heap allocation per string field, per row, everywhere. +2. **`ProcessArgs`** — the function that rewrites named SQL placeholders (`:w_id` → `$1`) ran a regex scan and `strings.Builder` assembly on every single query execution. SQL templates don't change between calls, but nothing was cached. +3. **`*stroppy.Value` boxing** — every generated value was wrapped in a protobuf oneof struct before being handed to the driver. One allocation per value, regardless of type. + +These three accounted for most of the non-sobek heap activity. + +## The Fixes + +### String generation + +The `strings.Builder` approach in `WordCutter` accumulates characters into a buffer and then calls `.String()` to return a copy. The copy is unnecessary — the caller only needs the string long enough to pass it to the driver, and the buffer will be reset immediately after. + +The fix: replace `.String()` with `unsafe.String(unsafe.SliceData(buf), len(buf))`. This returns a string header that aliases the internal buffer directly. No allocation. The lifetime contract is the same as before — valid until the next `Cut()` call — which the caller already respected. + +We also rewrote the character tape. The original picked a random Unicode range, then called `IntN` twice per character. The new version caches one `uint64` from the PRNG and extracts `log2(alphabetSize)` bits per character with a bitmask. For a 52-character alphabet (A-Z, a-z), that's one PRNG call per ~10 characters instead of two per character. The lookup table is sized to the next power of two for cheap masking. + +Combined: `WordCutter.Cut` went from 161 ns / 1 alloc to 39 ns / 0 allocs. + +### SQL template caching + +`ProcessArgs` was doing real work on every call: a regex scan to find `:param` tokens, and a `strings.Builder` pass to rebuild the SQL with positional placeholders. All of this is determined by the SQL template and the dialect — it doesn't depend on the argument values at all. + +The fix is a `sync.Map` keyed by `dialect.Placeholder(0) + "|" + sqlStr`. The first call for each `(dialect, sql)` pair parses and stores a `parsedQuery` struct. Every subsequent call does a map lookup and fills the argument slice. The cache is capped at 1 000 entries. + +Result: 4 636 ns / 13 allocs → 186 ns / 2 allocs. The 96% reduction is large because the cached path is almost nothing — one map lookup, one slice fill. + +### `*stroppy.Value` boxing + +The generator interface previously returned `(*stroppy.Value, error)`, where `*stroppy.Value` is a protobuf oneof that wraps the actual value. Every call to `Next()` allocated a new wrapper struct. + +We changed `Next()` to return `(any, error)` with native Go types: `int64`, `float64`, `uuid.UUID`, `time.Time`, `decimal.Decimal`, `*string`. Types narrower than 64 bits are widened so they fit in the interface word without a `convT` allocation. + +For types that still heap-allocate (time.Time, decimal.Decimal), we use a "slotted" generator: the generator owns a single value slot in a closure and returns `*T`. A pointer is always pointer-sized, so boxing it as `any` is zero-alloc. The caller must not hold the pointer past the next `Next()` call — the same constraint as `WordCutter.Cut`. + +Result: integer and string generators dropped to zero allocations per call. DateTime: 127 ns / 4 allocs → 17 ns / 0 allocs. + +### Smaller fixes + +A few smaller wins rounded out the PR: + +- **`UniqueDistribution`**: replaced `atomic.Pointer[T]` (allocates a new value on every CAS) with `atomic.Uint64` (plain counter). −68%, 1 alloc → 0. +- **`UniformDistribution` integer path**: was using `Float64()` + `math.Round()` for integer ranges. Replaced with `Uint64N(span+1)`. −43%. +- **`TupleGenerator`**: replaced a goroutine + buffered channel with an inline depth-first state machine. +- **genIDs**: `QueryBuilder` now precomputes generated ID lists at construction, not per batch. + +## The Numbers + +### Microbenchmarks + +Running `go test -bench=. -benchmem -count=10` before and after, with `benchstat` for comparison: + +![Microbenchmark ns/op, log scale](./micro_ns.png) + +| Benchmark | Before | After | Δ | +|-----------|-------:|------:|---| +| `CharTape_Next` | 9.7 ns | 2.4 ns | −75% | +| `WordCutter_Cut` | 161 ns / 1 alloc | 39 ns / **0** | −76% | +| `StringGenerator_Next` | 169 ns / 1 alloc | 40 ns / **0** | −76% | +| `UniqueNumber_Next` | 17.4 ns / 1 alloc | 5.5 ns / **0** | −68% | +| `Generator_String` | 232 ns / 2 allocs | 58 ns / **0** | −75% | +| `Generator_DateTime` | 127 ns / 4 allocs | 17 ns / **0** | −87% | +| `Generator_Decimal` | 349 ns / 9 allocs | 116 ns / 1 | −67% | +| `ProcessArgs` | 4 636 ns / 13 allocs | 186 ns / 2 | **−96%** | + +The log scale on the chart is needed because `ProcessArgs` (4 636 ns → 186 ns) and `CharTape_Next` (9.7 ns → 2.4 ns) live in completely different ranges. + +### End-to-end throughput + +The `tpcc/pick` workload against the noop driver, varying VU count. Each data point is the median of three 30-second runs. + +![E2E throughput before/after, noop driver](./e2e_throughput.png) + +| VUS | Before | After | Δ | +|----:|-------:|------:|---| +| 1 | 25 424/s | 29 421/s | +15.7% | +| 2 | 43 175/s | 50 072/s | +16.0% | +| 4 | 65 919/s | 74 566/s | +13.1% | +| 8 | 90 264/s | 100 419/s | +11.2% | +| 16 | 100 170/s | 111 489/s | +11.3% | + +The gain is uniform across VU counts, which confirms it's per-operation work, not something contention-related. The scaling curve itself doesn't change — both versions plateau at the same point, limited by the sobek event loop scheduler, not the generators. + +Against **pg-noop** (real TCP, full PostgreSQL wire protocol on localhost) the gain is +11.5% at VUS=1, +8.8% at VUS=8. Smaller, because the ~51 µs protocol overhead per transaction dilutes the per-operation generator savings. + +### Data generation + +The most visible improvement is in `load_data` — the phase that generates and inserts all TPC-C tables before the workload starts. This runs entirely in Go with no JS overhead per row, so it directly measures generation throughput. + +![Per-table speedup at SF=20](./load_speedup.png) + +| Scale factor | Rows | Before | After | Speedup | +|-------------:|-----:|-------:|------:|--------:| +| 1 | 231K | 1.20s | 0.32s | 3.8× | +| 20 | 2.7M | 20.2s | 5.5s | 3.7× | +| 100 | 13.1M | 103s | 27.7s | 3.7× | + +The 3.7× figure is consistent across all scale factors, which is what you'd expect — it's a per-row cost reduction, so the benefit scales linearly with data volume. + +The `district` table (7.6×) benefits more than the others because it generates many short strings relative to its row count. `customer` and `stock` have more varied fields but the string-heavy columns (`c_data` at 300–500 characters, the ten `s_dist_*` fields) still drive most of the work. + +## Where We Stopped + +After these changes, a fresh pprof profile shows sobek (the Go JavaScript runtime that runs workload scripts) as the dominant cost. That's not ours to optimize. The generator pipeline is no longer visible as a distinct entry. + +The steady-state improvement (+11–16%) is real but not large. It's limited by how much of the per-transaction time is spent in Go generators versus sobek. The `load_data` improvement (3.7×) is larger because that path doesn't cross the JS boundary at all — it's pure Go generation. + +For practical purposes: with this change, stroppy's generator overhead is unlikely to be the bottleneck in most setups. The data loading phase is substantially faster at any scale, which makes iteration on large-scale tests faster. + +--- + +The [previous post](/blog/measuring-stroppy-before-measuring-databases) covers the noop driver and pg-noop setup used throughout this work. The full changes are in [PR #62](https://github.com/stroppy-io/stroppy/pull/62). diff --git a/blog/2026-04-08-stroppy-perf/load_speedup.gnu b/blog/2026-04-08-stroppy-perf/load_speedup.gnu new file mode 100644 index 0000000..bc70317 --- /dev/null +++ b/blog/2026-04-08-stroppy-perf/load_speedup.gnu @@ -0,0 +1,31 @@ +set terminal pngcairo size 1640,880 enhanced font "Sans,12" fontscale 2 linewidth 2 +set output "load_speedup.png" + +set style fill solid 0.85 border -1 +set style data histograms +set boxwidth 0.6 + +set title "load\\_data speedup by table — SF=20, noop driver" font "Sans,13" +set xlabel "" +set ylabel "Speedup (×)" +set yrange [0:9] +set grid y lt 0 lc "grey" lw 0.5 +set key off + +# label bars with value +set label 1 "3.6×" at 0, 3.6+0.25 center font "Sans,11" +set label 2 "7.6×" at 1, 7.6+0.25 center font "Sans,11" +set label 3 "3.9×" at 2, 3.9+0.25 center font "Sans,11" +set label 4 "3.6×" at 3, 3.6+0.25 center font "Sans,11" + +# reference line at 1× +set arrow from -0.5, 1 to 3.5, 1 nohead lc rgb "#cc3333" lw 1.5 dt 2 + +$data << EOD +"item" 3.6 +"district" 7.6 +"customer" 3.9 +"stock" 3.6 +EOD + +plot $data using 2:xtic(1) lc rgb "#e49444" diff --git a/blog/2026-04-08-stroppy-perf/load_speedup.png b/blog/2026-04-08-stroppy-perf/load_speedup.png new file mode 100644 index 0000000000000000000000000000000000000000..67339e7641faf274703968e97a5ab698b6d43f09 GIT binary patch literal 43700 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 X_R(=k|N9H#x%cXu>fP2kbpC$;dzxdU literal 0 HcmV?d00001 From a76483724cfb168b96563fda59e71b9910ac47bd Mon Sep 17 00:00:00 2001 From: Nikita Aleksandrov Date: Wed, 8 Apr 2026 00:31:45 +0300 Subject: [PATCH 2/5] you -> we --- blog/2026-04-07-noop-drivers/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/blog/2026-04-07-noop-drivers/index.md b/blog/2026-04-07-noop-drivers/index.md index 5cca332..b0dcd9b 100644 --- a/blog/2026-04-07-noop-drivers/index.md +++ b/blog/2026-04-07-noop-drivers/index.md @@ -5,7 +5,7 @@ authors: [stroppy-authors] tags: [development, drivers, noop, pg-noop, internals] --- -When you run a database benchmark, the tool itself is in the picture. If stroppy can only push 12 000 transactions per second, no database will ever look faster than that in your results — not because the database is slow, but because stroppy ran out of steam first. Knowing that ceiling matters. +When running a database benchmark, the tool itself is in the picture. If stroppy can only push 12 000 transactions per second, no database will ever look faster than that in your results — not because the database is slow, but because stroppy ran out of steam first. Knowing that ceiling matters. We added two noop layers to make that ceiling easy to find: one in-process (a dummy driver) and one over the wire (a standalone pg-noop server). Together they bracket stroppy's throughput with and without the PostgreSQL protocol stack in the way. @@ -49,14 +49,14 @@ The same workload against pg-noop yields about **41 000 iterations/s** at VUS=8 | noop (in-process) | 29 421/s | 100 419/s | | pg-noop (TCP localhost) | 11 814/s | 41 352/s | -## What These Numbers Tell You +## What These Numbers Tell Us -Before comparing databases, you have two useful data points: +Before comparing databases, we have two useful data points: - **Noop ceiling**: the hard upper bound on stroppy's throughput on this hardware. Any result near this number means stroppy might be the bottleneck. - **pg-noop ceiling**: the upper bound when the full protocol stack is involved. Any result near this number means the database is doing very little work and the cost is mostly in the client. -If your production PostgreSQL throughput sits well below the pg-noop ceiling, you're in good shape — the database is being measured, not the tool. If it's close, it's worth investigating whether stroppy is the limiting factor. +If production PostgreSQL throughput sits well below the pg-noop ceiling, we're in good shape — the database is being measured, not the tool. If it's close, it's worth investigating whether stroppy is the limiting factor. These baselines are also useful for cross-machine comparisons: the noop and pg-noop numbers characterize the test machine itself, which helps when moving between hardware or comparing results across environments. From f76ea8449d154330ed749a53bc0fb522d49db930 Mon Sep 17 00:00:00 2001 From: Nikita Aleksandrov Date: Wed, 8 Apr 2026 01:05:23 +0300 Subject: [PATCH 3/5] work on intros --- blog/2026-04-07-noop-drivers/index.md | 8 ++++---- blog/2026-04-08-stroppy-perf/index.md | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/blog/2026-04-07-noop-drivers/index.md b/blog/2026-04-07-noop-drivers/index.md index b0dcd9b..b97fd1c 100644 --- a/blog/2026-04-07-noop-drivers/index.md +++ b/blog/2026-04-07-noop-drivers/index.md @@ -5,9 +5,9 @@ authors: [stroppy-authors] tags: [development, drivers, noop, pg-noop, internals] --- -When running a database benchmark, the tool itself is in the picture. If stroppy can only push 12 000 transactions per second, no database will ever look faster than that in your results — not because the database is slow, but because stroppy ran out of steam first. Knowing that ceiling matters. +Stroppy's own throughput caps benchmark results — if stroppy tops out at 12 000 iterations per second, no database under test will appear faster than that, regardless of its actual performance. -We added two noop layers to make that ceiling easy to find: one in-process (a dummy driver) and one over the wire (a standalone pg-noop server). Together they bracket stroppy's throughput with and without the PostgreSQL protocol stack in the way. +Stroppy already has two points where it communicates with the outside world: the driver layer, which handles query construction and dispatch, and the wire protocol layer beneath it. We added a noop sink to each — an in-process driver that discards all operations and a standalone pg-noop server that speaks the full PostgreSQL wire protocol but returns empty results. Together they give us throughput ceilings with and without the protocol stack involved. @@ -62,8 +62,8 @@ These baselines are also useful for cross-machine comparisons: the noop and pg-n --- -Writing your own driver for a different database follows the same pattern as the noop driver — see [Extensibility](/docs/extensibility) for a walkthrough. +Writing a driver for a different database follows the same pattern as the noop driver — see [Extensibility](/docs/extensibility) for a walkthrough. --- -That 100 000 iter/s ceiling didn't start there. The [next post](/blog/stroppy-generator-performance) covers the pprof sessions on stroppy itself and the generator-pipeline changes behind the numbers you just saw. +The numbers in the tables above are after the generator-pipeline optimizations — the [next post](/blog/stroppy-generator-performance) covers the profiling sessions and changes that produced them. diff --git a/blog/2026-04-08-stroppy-perf/index.md b/blog/2026-04-08-stroppy-perf/index.md index df95ed5..cdb9ddd 100644 --- a/blog/2026-04-08-stroppy-perf/index.md +++ b/blog/2026-04-08-stroppy-perf/index.md @@ -5,9 +5,9 @@ authors: [stroppy-authors] tags: [performance, internals, generators, profiling, tpc-c] --- -The [previous post](/blog/measuring-stroppy-before-measuring-databases) ended with a ceiling: 100 000 iterations per second through the noop driver. That raised an obvious question — was that any good? We built the noop driver to measure stroppy, not a database. So what is stroppy doing with its time when there is no database? We pulled a pprof profile to find out. This post covers what the profiles showed and what we changed. +The [previous post](/blog/measuring-stroppy-before-measuring-databases) set up the measurement methodology: the noop driver and pg-noop let us measure stroppy's own overhead with no database involved. Using that setup, we ran pprof against stroppy to understand where its time goes. The generator pipeline was the main target, and this post covers what the profiles showed and what we changed. -The short answer: stroppy's Go generator pipeline had a handful of avoidable allocations and one surprisingly expensive hot path. Fixing them took a full PR. The end-to-end throughput improvement is moderate — about 11–16% on a steady-state workload. The data generation speedup is more dramatic: 3.7× across the board. Neither number is astonishing, but the work was worth doing and some of the details were interesting. +Stroppy's Go generator pipeline had a handful of avoidable allocations and one hot path doing redundant work on every query. Fixing them is the subject of a single PR. The end-to-end throughput improvement is about 11–16% on a steady-state workload; the data loading phase improves by 3.7× because it runs entirely in Go with no JS boundary per row. @@ -119,7 +119,7 @@ The most visible improvement is in `load_data` — the phase that generates and | 20 | 2.7M | 20.2s | 5.5s | 3.7× | | 100 | 13.1M | 103s | 27.7s | 3.7× | -The 3.7× figure is consistent across all scale factors, which is what you'd expect — it's a per-row cost reduction, so the benefit scales linearly with data volume. +The 3.7× figure is consistent across all scale factors — it's a per-row cost reduction, so the benefit scales linearly with data volume. The `district` table (7.6×) benefits more than the others because it generates many short strings relative to its row count. `customer` and `stock` have more varied fields but the string-heavy columns (`c_data` at 300–500 characters, the ten `s_dist_*` fields) still drive most of the work. From 9587e48c7e976daacac5078f92e87c2d9dcb3a41 Mon Sep 17 00:00:00 2001 From: Nikita Aleksandrov Date: Wed, 8 Apr 2026 01:59:23 +0300 Subject: [PATCH 4/5] a bit more info packed inside --- blog/2026-04-07-noop-drivers/index.md | 13 +++++-------- blog/2026-04-08-stroppy-perf/index.md | 4 ++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/blog/2026-04-07-noop-drivers/index.md b/blog/2026-04-07-noop-drivers/index.md index b97fd1c..194f0f0 100644 --- a/blog/2026-04-07-noop-drivers/index.md +++ b/blog/2026-04-07-noop-drivers/index.md @@ -17,7 +17,7 @@ The first layer is a driver inside stroppy that accepts all operations and disca It serves two purposes. During development, it gives us a full E2E path without requiring a database — useful for testing workload scripts and driver logic before spinning anything up. And during benchmarking, it measures stroppy's absolute throughput ceiling: the full stroppy cost with no network and no database in the picture. -Running the TPC-C `pick` workload against the noop driver on our test machine: +Running the TPC-C `pick` workload against the noop driver on our test machine (Intel Core Ultra 7 155H, 22 cores, 32 GB RAM): ```bash stroppy run tpcc/pick -d noop -- --vus 8 --duration 30s @@ -40,7 +40,7 @@ stroppy run tpcc/pick -- --vus 8 --duration 30s No configuration needed on stroppy's side — it connects to localhost:5432 and sees a normal PostgreSQL server. -The implementation is small. It's built on the Rust [pgwire](https://github.com/sunng87/pgwire) library: a `NoopHandler` that implements the four required traits (`StartupHandler`, `SimpleQueryHandler`, `ExtendedQueryHandler`, `CopyHandler`), a Tokio acceptor loop, and jemalloc for the musl build. That's the whole thing. +The implementation is built on [pgwire](https://github.com/sunng87/pgwire), a Rust library that several newer databases use as their PostgreSQL wire protocol layer. On top of it: a `NoopHandler` implementing four traits (`StartupHandler`, `SimpleQueryHandler`, `ExtendedQueryHandler`, `CopyHandler`), a Tokio acceptor loop, and jemalloc for the musl build. Structurally, pg-noop is a PostgreSQL server — it just has no storage behind it. The same workload against pg-noop yields about **41 000 iterations/s** at VUS=8 — versus 100 000 against the in-process noop. The gap is the PostgreSQL wire protocol overhead on localhost: connection management, query serialization, network round-trips, response parsing. At VUS=1 the uncontended per-transaction cost difference is about 51 µs — the protocol cost with no database work. @@ -51,14 +51,11 @@ The same workload against pg-noop yields about **41 000 iterations/s** at VUS=8 ## What These Numbers Tell Us -Before comparing databases, we have two useful data points: +The noop ceiling is the hard upper bound on stroppy's throughput on this hardware — any benchmark result near it means stroppy is the bottleneck, not the database. The pg-noop ceiling adds the protocol layer: if a real database sits close to that number, the cost is mostly in the client, not the server. -- **Noop ceiling**: the hard upper bound on stroppy's throughput on this hardware. Any result near this number means stroppy might be the bottleneck. -- **pg-noop ceiling**: the upper bound when the full protocol stack is involved. Any result near this number means the database is doing very little work and the cost is mostly in the client. +These numbers also characterize the test machine itself, which matters when comparing results across environments or hardware generations. -If production PostgreSQL throughput sits well below the pg-noop ceiling, we're in good shape — the database is being measured, not the tool. If it's close, it's worth investigating whether stroppy is the limiting factor. - -These baselines are also useful for cross-machine comparisons: the noop and pg-noop numbers characterize the test machine itself, which helps when moving between hardware or comparing results across environments. +One more use: pg-noop can run on a remote node. Pointing stroppy at it over real network infrastructure gives a clean measurement of what latency and bandwidth alone cost, without any database noise. That's useful when evaluating multi-node or cross-datacenter setups before involving an actual database cluster. --- diff --git a/blog/2026-04-08-stroppy-perf/index.md b/blog/2026-04-08-stroppy-perf/index.md index cdb9ddd..9794fdf 100644 --- a/blog/2026-04-08-stroppy-perf/index.md +++ b/blog/2026-04-08-stroppy-perf/index.md @@ -7,7 +7,7 @@ tags: [performance, internals, generators, profiling, tpc-c] The [previous post](/blog/measuring-stroppy-before-measuring-databases) set up the measurement methodology: the noop driver and pg-noop let us measure stroppy's own overhead with no database involved. Using that setup, we ran pprof against stroppy to understand where its time goes. The generator pipeline was the main target, and this post covers what the profiles showed and what we changed. -Stroppy's Go generator pipeline had a handful of avoidable allocations and one hot path doing redundant work on every query. Fixing them is the subject of a single PR. The end-to-end throughput improvement is about 11–16% on a steady-state workload; the data loading phase improves by 3.7× because it runs entirely in Go with no JS boundary per row. +Stroppy's Go generator pipeline had a handful of avoidable allocations and one hot path doing redundant work on every query. Fixing them is the subject of a single PR. The end-to-end throughput improvement is about 11–16% on a steady-state workload; the data loading phase improves by 3.7× — that phase runs entirely in Go, without the per-iteration overhead of sobek, the JavaScript runtime stroppy uses to execute workload scripts. @@ -91,7 +91,7 @@ The log scale on the chart is needed because `ProcessArgs` (4 636 ns → 186 ns) ### End-to-end throughput -The `tpcc/pick` workload against the noop driver, varying VU count. Each data point is the median of three 30-second runs. +The `tpcc/pick` workload against the noop driver, varying VU count. Each data point is the median of three 30-second runs (Intel Core Ultra 7 155H, 22 cores, 32 GB RAM). ![E2E throughput before/after, noop driver](./e2e_throughput.png) From 7c748077c4e673107532f6bd10247c3c88516c41 Mon Sep 17 00:00:00 2001 From: Nikita Aleksandrov Date: Wed, 8 Apr 2026 12:49:06 +0300 Subject: [PATCH 5/5] post 1 intro logic --- blog/2026-04-07-noop-drivers/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2026-04-07-noop-drivers/index.md b/blog/2026-04-07-noop-drivers/index.md index 194f0f0..d7b170d 100644 --- a/blog/2026-04-07-noop-drivers/index.md +++ b/blog/2026-04-07-noop-drivers/index.md @@ -5,7 +5,7 @@ authors: [stroppy-authors] tags: [development, drivers, noop, pg-noop, internals] --- -Stroppy's own throughput caps benchmark results — if stroppy tops out at 12 000 iterations per second, no database under test will appear faster than that, regardless of its actual performance. +If stroppy tops out at 12 000 iterations per second, no database under test will appear faster than that, regardless of its actual performance, in other words, stroppy's own throughput caps benchmark results. Stroppy already has two points where it communicates with the outside world: the driver layer, which handles query construction and dispatch, and the wire protocol layer beneath it. We added a noop sink to each — an in-process driver that discards all operations and a standalone pg-noop server that speaks the full PostgreSQL wire protocol but returns empty results. Together they give us throughput ceilings with and without the protocol stack involved.