Skip to content

Commit fb59ab4

Browse files
committed
perf(checkpoint): enlarge exact MuHash batches
Raise the exact checkpoint MuHash batch bounds and match the lane count to the active Rayon pool. This removes most checkpoint MuHash scheduling overhead without weakening the independent listener-versus-traversal check. A direct three-run interleaved comparison against the pre-buffer checkpoint baseline reduced median process wall time from 35.104562s to 33.095760s (1.060697x) and checkpoint tail time from 3.736965s to 1.645882s (2.270494x). C150 checkpoint bytes stayed identical, and fjall, RocksDB, and redb reopen proofs passed.
1 parent 3092eab commit fb59ab4

4 files changed

Lines changed: 395 additions & 4 deletions

File tree

CONCEPTS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,17 @@ not the checkpoint format or durability boundary. Its `finish` operation owns
144144
the checked flush so a caller cannot publish a digest for buffered bytes that
145145
were not handed to the file.
146146

147+
### Checkpoint MuHash batch
148+
149+
The independent checkpoint traversal derives CoinStats and MuHash again instead
150+
of trusting the rolling listener that supplies live state. It encodes exact coin
151+
preimages into a bounded arena and computes insert-only partial MuHash values in
152+
parallel. The arena holds at most 262,144 coins or 16 MiB. Each flush uses no
153+
more lanes than the active Rayon pool or the 32-lane cap. The larger batch
154+
reduces partial-value construction and combination. It does not remove the
155+
listener-versus-traversal check, change preimage bytes, change snapshot bytes,
156+
or weaken checkpoint durability.
157+
147158
### Coalesced TxIndex wake
148159
The nonblocking notification published immediately after a committed `applied_tip.store`. The publisher increments an atomic revision with `Release` ordering and calls `try_send` on a capacity-one channel. Channel tokens may coalesce or be dropped because they are only wake hints. While a forward batch is pending, each hint returns the worker to reconciliation without changing the batch's original fixed deadline. The worker checks the authoritative revision before it sleeps and also wakes on a bounded timeout when caught up.
149160

crates/coinstats/src/stats.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ const NARROW_EVENT_CHUNK_SIZE: usize = 16;
2828
const WIDE_EVENT_CHUNK_SIZE: usize = 4;
2929
const INLINE_EVENT_CHUNKS: usize = 64;
3030

31-
const PARALLEL_MUHASH_MAX_COINS: usize = 16_384;
32-
const PARALLEL_MUHASH_MAX_BYTES: usize = 2 * 1024 * 1024;
33-
const PARALLEL_MUHASH_MAX_LANES: usize = 16;
31+
const PARALLEL_MUHASH_MAX_COINS: usize = 262_144;
32+
const PARALLEL_MUHASH_MAX_BYTES: usize = 16 * 1024 * 1024;
33+
const PARALLEL_MUHASH_MAX_LANES: usize = 32;
3434

3535
/// Exact byte length of the stable `CoinStats` encoding.
3636
pub const COIN_STATS_ENCODED_LEN: usize = 804;
@@ -292,7 +292,11 @@ impl EncodedPreimageArena {
292292
muhash.insert(&self.bytes[start..self.ends[index]]);
293293
}
294294
} else {
295-
let lane_count = self.ends.len().min(PARALLEL_MUHASH_MAX_LANES);
295+
let lane_count = self
296+
.ends
297+
.len()
298+
.min(PARALLEL_MUHASH_MAX_LANES)
299+
.min(rayon::current_num_threads());
296300
let lane_len = self.ends.len().div_ceil(lane_count);
297301
// Rayon collects scoped jobs before returning or propagating a panic,
298302
// so no lane can retain arena slices after this flush.
@@ -1253,6 +1257,18 @@ mod tests {
12531257
assert_eq!(stats.to_bytes(), serial.into_stats().to_bytes());
12541258
}
12551259

1260+
#[test]
1261+
fn parallel_muhash_matches_serial_at_configured_pool_widths() {
1262+
let coins = generated_coins(2_049, &[0, 1, 252, 253, 65_535]);
1263+
for width in [1, 4] {
1264+
rayon::ThreadPoolBuilder::new()
1265+
.num_threads(width)
1266+
.build()
1267+
.expect("build test pool")
1268+
.install(|| assert_parallel_serialized_match(&coins));
1269+
}
1270+
}
1271+
12561272
proptest! {
12571273
#![proptest_config(ProptestConfig::with_cases(16))]
12581274
#[test]
Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
{
2+
"schema": "bitcoin-rs-checkpoint-muhash-batching-custody",
3+
"version": 1,
4+
"source_head": "1fd6394",
5+
"source_head_is_dirty_base": true,
6+
"coinstats_source_sha256": "4847edfa772c64eb03fcf099621e2684a716b3eb1b9ccccc0594614cde2cef53",
7+
"candidate": "Increase the exact checkpoint MuHash arena to 262144 coins or 16 MiB and bound its 32-lane cap by the active Rayon pool width.",
8+
"contract": {
9+
"coin_preimage_change": false,
10+
"muhash_operation_change": false,
11+
"listener_traversal_cross_check_removed": false,
12+
"snapshot_format_change": false,
13+
"durability_change": false,
14+
"max_coins": 262144,
15+
"max_bytes": 16777216,
16+
"max_lanes": 32,
17+
"lanes_bounded_by_active_pool": true
18+
},
19+
"dependency_basis": {
20+
"rayon_pinned": "1.12.0",
21+
"rayon_current_num_threads_documentation": "https://docs.rs/rayon/1.12.0/rayon/fn.current_num_threads.html"
22+
},
23+
"attribution": {
24+
"probe": "Keep the complete CoinStats traversal, disable only independent traversal MuHash, and supply the listener trailer.",
25+
"probe_is_shippable": false,
26+
"reason_not_shippable": "It makes the listener-versus-traversal MuHash check tautological.",
27+
"runs": 3,
28+
"process_wall_seconds": [
29+
32.93800631701015,
30+
32.4295844680164,
31+
33.19030102016404
32+
],
33+
"process_wall_median_seconds": 32.93800631701015,
34+
"checkpoint_tail_seconds": [
35+
1.3393970800101478,
36+
1.2357068540163993,
37+
1.223520692164044
38+
],
39+
"checkpoint_tail_median_seconds": 1.2357068540163993,
40+
"baseline_checkpoint_tail_median_seconds": 2.660570781035041,
41+
"attributed_muhash_seconds": 1.4248639270186416,
42+
"checkpoint_tail_ceiling_speedup": 2.1530760085917042,
43+
"probe_reverted": true
44+
},
45+
"experiments": [
46+
{
47+
"iteration": 1,
48+
"max_coins": 131072,
49+
"max_bytes": 8388608,
50+
"max_lanes": 32,
51+
"pool_matched": false,
52+
"default_checkpoint_tail_seconds": 1.8342238790803194,
53+
"rayon4_checkpoint_tail_seconds": 2.75397786602246,
54+
"decision": "continue"
55+
},
56+
{
57+
"iteration": 2,
58+
"max_coins": 131072,
59+
"max_bytes": 8388608,
60+
"max_lanes": 32,
61+
"pool_matched": true,
62+
"default_checkpoint_tail_seconds": 1.7204900450813767,
63+
"rayon4_checkpoint_tail_seconds": 2.7815842599170395,
64+
"decision": "continue"
65+
},
66+
{
67+
"iteration": 3,
68+
"max_coins": 262144,
69+
"max_bytes": 16777216,
70+
"max_lanes": 32,
71+
"pool_matched": true,
72+
"default_checkpoint_tail_seconds": 1.6490747221791722,
73+
"rayon4_checkpoint_tail_seconds": 2.60376425507674,
74+
"decision": "accept for final panel"
75+
},
76+
{
77+
"iteration": 4,
78+
"max_coins": 524288,
79+
"max_bytes": 33554432,
80+
"max_lanes": 32,
81+
"pool_matched": true,
82+
"default_checkpoint_tail_seconds": 1.6295024169362335,
83+
"rayon4_checkpoint_tail_seconds": 2.5300227670151187,
84+
"decision": "revert",
85+
"reason": "The default-pool tail gain over 16 MiB was below the 1.02 marginal floor and eager arena memory doubled."
86+
}
87+
],
88+
"harness": {
89+
"build": "cargo build --release -p bitcoin-rs-node --features mimalloc --example mainnet_prefix_replay",
90+
"command_template": "taskset -c 0-31 mainnet_prefix_replay --stop-height 150000 --blocks-file $CORPUS --corpus-manifest $MANIFEST --assume-valid-height 0 --storage-backend fjall --data-dir $FRESH_DIR --output $OUTPUT",
91+
"production_pool_environment": "RAYON_NUM_THREADS=4",
92+
"cpu_affinity": "0-31",
93+
"cooldown_seconds": 30,
94+
"control_binary_sha256": "93f38df792c99661ae06c37e069a306b39cfb6db36c7f1b8e2789d77396a5fb4",
95+
"candidate_binary_sha256": "6e61e617e535fe995750f9f3dd1b70ed38bcf0f87327a00b919918029beac9a5"
96+
},
97+
"corpus": {
98+
"blocks_bytes": 689184213,
99+
"blocks_sha256": "e47d6d7632005214e8ce255c64ac6be96fdb5a9de0868d79d3d4222a3967d60f",
100+
"manifest_bytes": 19597242,
101+
"manifest_sha256": "324503f4f1edc4f3d02be131a8d2e5f14cef35be83e5fd0603777d818988c474"
102+
},
103+
"final_default_pool_panel": {
104+
"control": {
105+
"process_wall_seconds": [
106+
34.40757093206048,
107+
35.249265796970576,
108+
33.83484558202326
109+
],
110+
"process_wall_median_seconds": 34.40757093206048,
111+
"replay_seconds": [
112+
31.76920829,
113+
32.55097933,
114+
31.282470494000002
115+
],
116+
"replay_median_seconds": 31.76920829,
117+
"checkpoint_tail_seconds": [
118+
2.6383626420604784,
119+
2.698286466970579,
120+
2.552375088023261
121+
],
122+
"checkpoint_tail_median_seconds": 2.6383626420604784,
123+
"cpu_seconds": [
124+
257.21583100000134,
125+
257.242397,
126+
253.47063999999955
127+
],
128+
"cpu_median_seconds": 257.21583100000134,
129+
"rss_bytes": [
130+
711188480,
131+
678514688,
132+
691171328
133+
],
134+
"rss_median_bytes": 691171328
135+
},
136+
"candidate": {
137+
"process_wall_seconds": [
138+
33.69904471794143,
139+
34.26008653291501,
140+
33.479984638048336
141+
],
142+
"process_wall_median_seconds": 33.69904471794143,
143+
"replay_seconds": [
144+
31.984931969,
145+
32.518278738,
146+
31.758396844
147+
],
148+
"replay_median_seconds": 31.984931969,
149+
"checkpoint_tail_seconds": [
150+
1.7141127489414316,
151+
1.7418077949150117,
152+
1.721587794048336
153+
],
154+
"checkpoint_tail_median_seconds": 1.721587794048336,
155+
"cpu_seconds": [
156+
253.6696839999986,
157+
249.70437500000116,
158+
246.52076900000066
159+
],
160+
"cpu_median_seconds": 249.70437500000116,
161+
"rss_bytes": [
162+
697970688,
163+
712667136,
164+
702058496
165+
],
166+
"rss_median_bytes": 702058496
167+
},
168+
"comparison": {
169+
"checkpoint_tail_speedup": 1.5325170468688876,
170+
"process_wall_speedup": 1.0210251127309204,
171+
"cpu_speedup": 1.0300813952498835,
172+
"rss_ratio_candidate_over_control": 1.0157517645176393,
173+
"passes_checkpoint_gate": true,
174+
"whole_process_regressed": false
175+
}
176+
},
177+
"final_production_pool_panel": {
178+
"rayon_threads": 4,
179+
"control": {
180+
"process_wall_seconds": [
181+
37.56642260006629,
182+
36.598227948881686,
183+
36.529325338080525
184+
],
185+
"process_wall_median_seconds": 36.598227948881686,
186+
"replay_seconds": [
187+
33.56051712,
188+
32.736133881,
189+
32.691488462
190+
],
191+
"replay_median_seconds": 32.736133881,
192+
"checkpoint_tail_seconds": [
193+
4.005905480066289,
194+
3.862094067881685,
195+
3.837836876080523
196+
],
197+
"checkpoint_tail_median_seconds": 3.862094067881685,
198+
"cpu_median_seconds": 240.84249900000032,
199+
"rss_median_bytes": 664809472
200+
},
201+
"candidate": {
202+
"process_wall_seconds": [
203+
35.73458459507674,
204+
35.044127754168585,
205+
35.221993083134294
206+
],
207+
"process_wall_median_seconds": 35.221993083134294,
208+
"replay_seconds": [
209+
33.13082034,
210+
32.371659443,
211+
32.586765616
212+
],
213+
"replay_median_seconds": 32.586765616,
214+
"checkpoint_tail_seconds": [
215+
2.60376425507674,
216+
2.6724683111685863,
217+
2.6352274671342926
218+
],
219+
"checkpoint_tail_median_seconds": 2.6352274671342926,
220+
"cpu_median_seconds": 238.24492500000088,
221+
"rss_median_bytes": 648142848
222+
},
223+
"comparison": {
224+
"checkpoint_tail_speedup": 1.4655638331219893,
225+
"process_wall_speedup": 1.039073168361003,
226+
"cpu_speedup": 1.0109029562749319,
227+
"rss_ratio_candidate_over_control": 0.9749302248208641,
228+
"passes_checkpoint_gate": true,
229+
"whole_process_regressed": false
230+
}
231+
},
232+
"combined_final_panel": {
233+
"run_order": [
234+
"control-r1",
235+
"candidate-r1",
236+
"candidate-r2",
237+
"control-r2",
238+
"control-r3",
239+
"candidate-r3"
240+
],
241+
"control": {
242+
"binary_sha256": "7228a24c41262dfe3aa2b75b5fccaad4cfd8d9837e77cfbde43e196b66223d3c",
243+
"process_wall_seconds": [35.1045624059625, 34.295129670063034, 35.332849437138066],
244+
"process_wall_median_seconds": 35.1045624059625,
245+
"replay_seconds": [31.367597369, 30.587133093, 31.346029328],
246+
"replay_median_seconds": 31.346029328,
247+
"checkpoint_tail_seconds": [3.7369650369624985, 3.707996577063035, 3.9868201091380655],
248+
"checkpoint_tail_median_seconds": 3.7369650369624985,
249+
"cpu_median_seconds": 255.5198849999997,
250+
"rss_median_bytes": 702283776
251+
},
252+
"candidate": {
253+
"binary_sha256": "6e61e617e535fe995750f9f3dd1b70ed38bcf0f87327a00b919918029beac9a5",
254+
"process_wall_seconds": [33.09576010587625, 32.60701943002641, 33.90933257387951],
255+
"process_wall_median_seconds": 33.09576010587625,
256+
"replay_seconds": [31.449878416, 30.972782442, 32.196223347],
257+
"replay_median_seconds": 31.449878416,
258+
"checkpoint_tail_seconds": [1.6458816898762514, 1.6342369880264123, 1.71310922687951],
259+
"checkpoint_tail_median_seconds": 1.6458816898762514,
260+
"cpu_median_seconds": 248.57780300000013,
261+
"rss_median_bytes": 708964352
262+
},
263+
"comparison": {
264+
"checkpoint_tail_speedup": 2.2704943252898504,
265+
"process_wall_speedup": 1.0606966660883421,
266+
"cpu_speedup": 1.0279271999197754,
267+
"rss_ratio_candidate_over_control": 1.0095126446435236,
268+
"passes_integrated_process_gate": true
269+
}
270+
},
271+
"run_artifacts": {
272+
"default-control-r1": {"bytes": 5415, "sha256": "c01e32176895a3ca8cad28a5c6cec28c9868395f2aea440cb222a13920d4a710"},
273+
"default-control-r2": {"bytes": 5439, "sha256": "e54df77ec5284e90a803266848102ea6e98485e2654b5a3b01d339d30c213d52"},
274+
"default-control-r3": {"bytes": 5431, "sha256": "59eafe4497b5dad2d695275d41b9fb6841b5cc2c5b340d06f309fd3b2a7bcc6a"},
275+
"default-candidate-r1": {"bytes": 5417, "sha256": "54d9ef78e80dd8c4538a3994009c7ce85567564f223cd6ee0eb7d51a15a99218"},
276+
"default-candidate-r2": {"bytes": 5419, "sha256": "22ecd9add45a32667a51ff56a811660f7aa02215a5944a55c1a93f1aeba4f6ed"},
277+
"default-candidate-r3": {"bytes": 5398, "sha256": "a141c2fac62254f3178a4c2b5b1f0e682e321c387382dbce1d355e2e1edac1a6"},
278+
"rayon4-control-r1": {"bytes": 5378, "sha256": "5a3daf44cdedfcdcce148f0624970bc352665fb2d8038c892d10587bbda02785"},
279+
"rayon4-control-r2": {"bytes": 5414, "sha256": "343a710975e4c37903fbcfb6eaea630d8cb9f8574b79e86a9b861c8ac10c0ec6"},
280+
"rayon4-control-r3": {"bytes": 5423, "sha256": "5a468edd2f42eab1428abc0b03a08abc7674f099a872a96fee9c43b6a878065b"},
281+
"rayon4-candidate-r1": {"bytes": 5405, "sha256": "c37162bd5ee1e80d45fcebe107814acbbb03c9608d51dfc7f38039f0b41c7df4"},
282+
"rayon4-candidate-r2": {"bytes": 5423, "sha256": "ee41f54a5177ca4a2b22ee238b72534e29bbb0cc5eed27bdaee2bf1bcbdcf1e8"},
283+
"rayon4-candidate-r3": {"bytes": 5408, "sha256": "79aebdde75d5bd5dc883dd35d05c4a1f86389e93bbbafe322b06a6ccf42b1459"},
284+
"combined-control-r1": {"bytes": 5410, "sha256": "dd045278f9907732965d4e9c9a7ce52b2b4990eb69f5197f53b5e15c0de03aca"},
285+
"combined-control-r2": {"bytes": 5435, "sha256": "07c69ee7eb365e7136d8b83bdce9612ca9987d0fe7a4199df15ab5b8c7676ff7"},
286+
"combined-control-r3": {"bytes": 5416, "sha256": "231235fdbb7ab52be8136513f36bab9cffbac3e071690954c3b0b3c17e92d541"},
287+
"combined-candidate-r1": {"bytes": 5439, "sha256": "dd228b0a7df3b3831bc06b84a211cd891c412681021d15623b2e75a83336336d"},
288+
"combined-candidate-r2": {"bytes": 5402, "sha256": "ee43f4072b8af90a058132d0506c0dcc7ea6584c3f71d73e3659c1949396c545"},
289+
"combined-candidate-r3": {"bytes": 5405, "sha256": "54c03281e870adeeeaf0f1107860be1765f75edb27c69c36fb1e9022b156d4b4"}
290+
},
291+
"checkpoint_artifact_identity": {
292+
"headers-v1.dat": {"bytes": 12000136, "sha256": "b5d2fed0fce64ae2596a16fd1f687d91c58c8012af509244cc648b85ba45a2b5"},
293+
"utxo-v4.dat": {"bytes": 72325450, "sha256": "8c9e7e5c03f7dedc179b2ce709a7289f4bd74e7f37ba31bba4c5f164212da83f"},
294+
"coinstats-v1.dat": {"bytes": 820, "sha256": "891ba1b2a26aec100a047ed4feb1066485b6326a9a2fb44138b84f2b40e08dba"},
295+
"manifest-v1.json": {"bytes": 2348, "sha256": "45a27b30fe32ddd820c922012ae1f429fc60b4689b05d097ecb26fa1245d36bc"},
296+
"CURRENT": {"bytes": 193, "sha256": "11a67430e324b42fa6a8b9a44dbabc8b044eddc65548f98b62d4ca8435f91684"},
297+
"matches_control_custody": true
298+
},
299+
"storage_backend_durability": {
300+
"binary_sha256": "d66c1b98bd82f30745b62a9bbda3855f9981530f74510e701b14924d87ff620b",
301+
"proof_directory": "/home/alpha/bench-g14/results/checkpoint-muhash-durability-254c1ljt",
302+
"fjall": {"proof_bytes": 1224, "proof_sha256": "7fd144699bf714c5b1d7b34b45b0a77790210710056c9f04b6e6f1a6a324bb9b", "checkpoint_generation": 2, "reopen_count": 2, "before_equals_after": true},
303+
"rocksdb": {"proof_bytes": 1226, "proof_sha256": "f64786a191597cb1099e3f42e08a21de8dd08a1903dee547d51f2baa4e921a78", "checkpoint_generation": 2, "reopen_count": 2, "before_equals_after": true},
304+
"redb": {"proof_bytes": 1223, "proof_sha256": "40a585ff8f1c146b7899f5d62a91d7ce487b9c43ac307d1a1f11e792519b917d", "checkpoint_generation": 2, "reopen_count": 2, "before_equals_after": true}
305+
},
306+
"identity": {
307+
"stop_height": 150000,
308+
"stop_hash": "0000000000000a3290f20e75860d505ce0e948a1d1d846bec7e39015d242884b",
309+
"utxo_count": 1127181,
310+
"total_amount": 749989998999999,
311+
"muhash": "383a0b41ac28ddf6ac91723b41527fa64c0b54451cee5f2c4b3823ef92117116",
312+
"utxo_hash_serialized_3": "c9c0a3928001d21a20cff79ba4163b4f0d4b4b637f10da6313bc9d310680436a"
313+
},
314+
"stacked_checkpoint_comparison": {
315+
"pre_buffer_process_wall_median_seconds": 35.1045624059625,
316+
"current_process_wall_median_seconds": 33.09576010587625,
317+
"stacked_process_wall_speedup": 1.0606966660883421,
318+
"measurement": "direct final interleaved panel"
319+
},
320+
"bitcoin_core_comparison": {
321+
"version": "31.1",
322+
"matched_process_wall_seconds": 62.888,
323+
"twofold_boundary_seconds": 31.444,
324+
"candidate_process_wall_seconds": 33.09576010587625,
325+
"candidate_speedup": 1.900182978085886,
326+
"seconds_above_twofold_boundary": 1.651760105876253,
327+
"twofold_goal_met": false
328+
}
329+
}

0 commit comments

Comments
 (0)