Skip to content

Commit f57c4b4

Browse files
committed
docs(perf): record the shipped window-batching result
The note said reverted. It is now shipped, and the numbers belong with it. Blocks 0..150,000 with full verification, three interleaved pairs pinned: 78.4s wall and 643.4s CPU become 69.6s and 558.4s. Core is 60.7s and 466.5s, so it still leads, by 1.15x on wall and 1.20x on CPU rather than 1.28x and 1.37x. The account of the first attempt stays. It failed for a more instructive reason than the second succeeded: a batch that recomputes the sequential path's preparation pays back exactly what it saves, and the tell is that the accelerated stage shrinks by about what the new stage costs. Also records where the time goes now. The dispatch is no longer the largest term, so the remaining gap is broad work across apply's own stages rather than one more structural change.
1 parent 88e618c commit f57c4b4

2 files changed

Lines changed: 50 additions & 5 deletions

File tree

CONCEPTS.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,21 @@ dispatch does not fix it and makes it worse, because it throttles the blocks
118118
that were scaling; only issuing fewer, larger dispatches does. See
119119
`docs/solutions/performance/script-batching-needs-a-split-apply-path.md`.
120120

121+
### Window script batching
122+
123+
Verifying the input scripts of several consecutive blocks in one parallel
124+
dispatch, so the fan-out is amortised over a run of blocks rather than paid per
125+
block. The window prepares each block against an ordered overlay, dispatches
126+
once, and issues a per-block proof; the blocks then commit one at a time and in
127+
order, so every rule needing committed state still sees the real chain. On
128+
mainnet 0..150_000 this took the replay from 78.4s / 643.4s CPU to 69.6s /
129+
558.4s, with the dispatch itself falling from 44.08s to 12.55s. The proof binds
130+
the block hash, its predecessor, the height, the flags, and the locktime cutoff,
131+
travels bundled with the prepared state it covers, and is re-checked against
132+
what the apply derives; a window that cannot be proven yields nothing and every
133+
block verifies normally. See
134+
`docs/solutions/performance/script-batching-needs-a-split-apply-path.md`.
135+
121136
### Front-half duplication
122137

123138
The failure mode where a batched fast path recomputes the sequential path's

docs/solutions/performance/script-batching-needs-a-split-apply-path.md

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
1-
# Cross-block script batching cuts crypto dispatch 3.5x, and pays it all back
1+
# Cross-block script batching: reverted once, then shipped
22

3-
Status: measured, implemented, reverted. The mechanism works. The integration
4-
does not, and this note says exactly why so the next attempt starts from the
5-
right shape.
3+
Status: **shipped.** The first attempt was a wash and was reverted; the second,
4+
built on a split apply path so preparation happens once, holds up.
5+
6+
| blocks 0..150,000, full verification | wall | CPU |
7+
|---|---|---|
8+
| Bitcoin Core 31.0 | 60.7s | 466.5s |
9+
| bitcoin-rs before | 78.4s | 643.4s |
10+
| bitcoin-rs after | **69.6s** | **558.4s** |
11+
12+
Three interleaved pairs, medians, pinned to `taskset -c 0-31`. Both axes
13+
improve, so this is not a wall-for-CPU trade. Core still leads: 1.15x on wall
14+
and 1.20x on CPU, down from 1.28x and 1.37x.
15+
16+
Script verification inside apply fell from 49.26s to 6.91s, and the dispatch it
17+
replaced from 44.08s across 21,474 fan-outs to 12.55s across 2,343.
18+
19+
The rest of this note is why the first attempt failed and what the second had to
20+
do differently. It is kept because the failure is more instructive than the
21+
success.
622

723
## The gap
824

@@ -143,7 +159,21 @@ There is no cheaper variant. Block `w+1`'s front half needs `w`'s committed
143159
state, which is precisely what the overlay substitutes for, so the front half
144160
cannot be hoisted without the overlay and cannot be shared without the split.
145161

146-
## What was kept
162+
## Where the time goes now
163+
164+
| stage | seconds |
165+
|---|---|
166+
| apply (all blocks, everything but scripts) | 26.51 |
167+
| script dispatch | 12.55 |
168+
| window preparation (kernel parse, tx plan, resolution) | 11.28 |
169+
| check preparation | 5.09 |
170+
| decode | 3.2 |
171+
172+
The dispatch is no longer the largest term, which is the point. Closing the
173+
remaining ~9s means broad work across apply's own stages, not one more
174+
structural change.
175+
176+
## What was kept from the first attempt
147177

148178
Nothing. The building blocks were correct and mutation-verified, but without a
149179
caller they are scaffolding, and a wired version that costs what it saves is

0 commit comments

Comments
 (0)