Commit 3219847
committed
d5104cf prevector: store `P2WSH`/`P2TR`/`P2PK` scripts inline (Lőrinc)
5212150 test: assert `CScript` allocation characteristics (Lőrinc)
65ac7f6 refactor: modernize `CScriptBase` definition (Lőrinc)
756da2a refactor: extract `STATIC_SIZE` constant to prevector (Lőrinc)
Pull request description:
This change is part of [[IBD] - Tracking PR for speeding up Initial Block Download](bitcoin/bitcoin#32043)
### Summary
The current `prevector` size of 28 bytes (chosen to fill the `sizeof(CScript)` aligned size) was introduced in 2015 (bitcoin/bitcoin#6914) before `SegWit` and `TapRoot`.
However, the increasingly common `P2WSH` and `P2TR` scripts are both 34 bytes, and are forced to use heap (re)allocation rather than efficient inline storage.
The core trade-off of this change is to eliminate heap allocations for common 34-36 byte scripts at the cost of increasing the base memory footprint of all `CScript` objects by 8 bytes (while still respecting peak memory usage defined by `-dbcache`).
### Context
Increasing the `prevector` size allows these scripts to be stored inline, avoiding heap allocations, reducing potential memory fragmentation, and improving performance during cache flushes. Massif analysis confirms a lower stable memory usage after flushing, suggesting the elimination of heap allocations outweighs the larger base size for common workloads.
Due to memory alignment, increasing the prevector size to 36 bytes doesn't change the overall `sizeof(CScript)` compared to an increase to 34 bytes, allowing us to include `P2PK` scripts as well at no additional memory cost.
<details>
<summary>Massif measurements</summary>
> dbcache=440
Massif before, with a heap threshold of `28`:
```bash
MB
744.1^#
|#: ::::::@: ::::::: :@:: @::::::::::::::@@
|#: ::::::@::::: ::: :@:::@:::::: :: ::::@
|#: ::::::@::::: ::: :@:::@:::::: :: ::::@
|#: ::::::@::::: ::: : :@:::@:::::: :: ::::@
|#: ::::::@::::: ::: : :@:::@:::::: :: ::::@
|#: ::::::@::::: ::: : :@:::@:::::: :: ::::@
|#::::::::@::::: ::: : :@:::@:::::: :: ::::@
|#::::::::@::::: ::: :::@:::@:::::: :: ::::@
|#::::::::@::::: ::: :::@:::@:::::: :: ::::@
|#::::::::@::::: ::: :::@:::@:::::: :: ::::@
|#::::::::@::::: ::: :::@:::@:::::: :: ::::@
|#::::::::@::::: :::::::@:::@:::::: :: ::::@
|#::::::::@::::: :::::::@:::@:::::: :: ::::@ :::::@:::::@:::::@:::::@::::
|#::::::::@::::: :::::::@:::@:::::: :: ::::@ :::::@:::::@:::::@:::::@::::
|#::::::::@::::: :::::::@:::@:::::: :: ::::@ :::::@:::::@:::::@:::::@::::
|#::::::::@::::: :::::::@:::@:::::: :: ::::@ :::::@:::::@:::::@:::::@::::
|#::::::::@::::: :::::::@:::@:::::: :: ::::@ :::::@:::::@:::::@:::::@::::
|#::::::::@::::: :::::::@:::@:::::: :: ::::@ :::::@:::::@:::::@:::::@::::
|#::::::::@::::: :::::::@:::@:::::: :: ::::@ :::::@:::::@:::::@:::::@::::
0 +----------------------------------------------------------------------->h
0 1.805
```
and after, with a heap threshold of `36`:
```bash
MB
744.2^ :
|# : ::::::::::: : : :: ::: @@:::::: :: :
|# : :::: :::::: : : :: ::: @ :: :: : :
|# : :::: ::::::: : :@:: ::: @ :: :: : :::
|# : :::: ::::::: : :@:: ::: @ :: :: : : :
|# : :::: ::::::: : :@:: ::: @ :: :: : : :
|# : :::: ::::::: : :@:: ::: @ :: :: : : :
|# :: :::: ::::::: : :@:: ::: @ :: :: : : :
|# :: :::: ::::::: : :@:: ::::@ :: :: : : :
|#:::: :::: ::::::: :::@:: ::::@ :: :: : : :
|#: ::::::: ::::::: :::@:: ::::@ :: :: @: : :
|#: ::::::: ::::::: :::@:::::::@ :: :: @: : :
|#: ::::::: ::::::::::::@:::::::@ :: :: @: : :
|#: ::::::: :::::::: :::@:::::::@ :: :: @: : :
|#: ::::::: :::::::: :::@:::::::@ :: :: @: : :::@:::@::::@::::::@:::::@::
|#: ::::::: :::::::: :::@:::::::@ :: :: @: : :::@:::@::::@::::::@:::::@::
|#: ::::::: :::::::: :::@:::::::@ :: :: @: : :::@:::@::::@::::::@:::::@::
|#: ::::::: :::::::: :::@:::::::@ :: :: @: : :::@:::@::::@::::::@:::::@::
|#: ::::::: :::::::: :::@:::::::@ :: :: @: : :::@:::@::::@::::::@:::::@::
|#: ::::::: :::::::: :::@:::::::@ :: :: @: : :::@:::@::::@::::::@:::::@::
0 +----------------------------------------------------------------------->h
0 1.618
```
---
> for `dbcache=4500`:
Massif before, with a heap threshold of `28`:
```bash
GB
4.565^ ::
| ##: @@::: :::: :@:::: :::: ::::
| # : @ :: ::: :@: :: : :: :::
| # : @ :: ::::: :@: :: : :: :::
| # : @ :: : ::: :@: :: @: :: :::
| # : @ :: : ::: :@: :: @: :: :::
| # : @ :: : ::: :@: :: @: :: :::
| # : @ :: : ::: :@: :: @: :: :::
| # : ::@ :: : ::: :@: :: @: :: :::
| # : : @ :: : ::: :@: :: @: :: :::
| # : : @ :: : ::: :@: :: @: ::::::
| # : : @ :: : ::: :@: :: @: ::::::
| # : : @ :: : ::: :@: :: @: ::::::
| # : : @ :: : ::: ::@: :: @: ::::::
| # : : @ :: : ::: ::@: :: @: ::::::
| # : : @ :: : ::: ::@: :: @: ::::::
| # : : @ :: : ::: ::@: :: @: :::::: @::
| # : : @ :: : ::: ::@: :: @: :::::: @:
| # : : @ :: : ::: ::@: :::@: :::::: @:
| # : : @ :: : ::: ::@: :::@: :::::: @: :::::::::::::::::::::::::::::@:::
0 +----------------------------------------------------------------------->h
0 1.500
```
and after, with a heap threshold of `36`:
```
GB
4.640^ :
| ##:: ::::: :::: ::::::@ ::::
| # :: : ::: :::: :: :::@ ::::
| # :: :: ::: :::: :: :::@ ::::
| # :: :: ::: ::::: :: :::@ ::::
| # :: :: ::: ::::: :: :::@ ::::
| # :: :: ::: ::::: :: :::@ ::::
| # :: :: ::: ::::: :: :::@ ::::
| # :: :: ::: ::::: :: :::@ :::: :@@
| # :: :: ::: ::::: ::: :::@ :::::::@
| # :: :: ::: ::::: ::: :::@ ::::: :@
| # :: :: ::: ::::: ::: :::@::::::: :@
| # ::::: ::: ::::: ::: :::@: ::::: :@
| # ::::: ::: ::::: ::: :::@: ::::: :@
| # ::::: :::::::::: ::: :::@: ::::: :@
| # ::::: :::: ::::: ::: :::@: ::::: :@
| # ::::: :::: ::::: ::: :::@: ::::: :@
| # ::::: :::: ::::::::: :::@: ::::: :@
| # ::::: :::: ::::::::: :::@: ::::: :@
| # ::::: :::: ::::::::: :::@: ::::: :@ ::::::@:::@:::@::::@:::::@::::@::
0 +----------------------------------------------------------------------->h
0 1.360
```
</details>
### Benchmarks and Memory
Performance benchmarks for `AssumeUTXO` load and flush show:
- Small dbcache (450MB): ~1-3% performance improvement (despite more frequent flushes)
- Large dbcache (4500MB): ~6-8% performance improvement due to fewer heap allocations (and basically the number of flushes)
- Very large dbcache (4500MB): ~5-6% performance improvement due to fewer heap allocations (and memory limit not being reached, so there's no memory penalty)
Full IBD and `-reindex-chainstate` with also show an overall ~3-4% speedup (both for smaller and larger dbcache values).
We haven't investigated using different `prevector` sizes based on script type, though this could be explored in the future if needed.
### Historical explanation for the speedup (by [Anthony Towns](bitcoin/bitcoin#32279 (comment)))
> I think the tradeoff is something like:
>
> * spends of p2pk, p2sh, p2pkh coins -- these cost 8 more bytes
> * spends of p2wpkh -- these cost 16 more bytes (sPK and scriptSig didn't need an allocation)
> * spends of p2wsh and p2tr -- these cost ~48 fewer bytes (save 64 byte allocation on 64bit system, lose 8 bytes for both scriptSig and sPK)
> * spends of nested p2wsh -- presumably save ~96 bytes, since the scriptSig would save an allocation, but I'm bundling it in the previous section
>
> Based on mainnet.observer stats for 2025-05-08, p2wpkh is about 55% of txs, p2tr is about 28%, p2pkh about 13%, p2wsh about 4% and the rest is noise, maybe? Those numbers net out to a saving of ~5.5 bytes per input. If p2wpkh rose from 55% to 80% and p2tr dropped to 20%, that would net to wasting ~3.2 bytes per input.
ACKs for top commit:
maflcko:
review ACK d5104cf 🐺
achow101:
reACK d5104cf
jonatack:
Review ACK d5104cf
andrewtoth:
ACK d5104cf
Tree-SHA512: 7c5271ebaf4f6d91dc4b679ecbde4b7d0467579f072289f30da988a17c38a552d0b8cdf0e9c001739975dd019894c35e541908571527916cec56e04a8e214ae2
File tree
6 files changed
+131
-28
lines changed- src
- bench
- script
- test
6 files changed
+131
-28
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
19 | | - | |
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
| 33 | + | |
34 | 34 | | |
35 | | - | |
| 35 | + | |
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
14 | | - | |
| 15 | + | |
| 16 | + | |
15 | 17 | | |
16 | 18 | | |
17 | 19 | | |
18 | 20 | | |
| 21 | + | |
19 | 22 | | |
20 | 23 | | |
21 | 24 | | |
| |||
27 | 30 | | |
28 | 31 | | |
29 | 32 | | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
34 | 37 | | |
35 | 38 | | |
36 | 39 | | |
37 | 40 | | |
38 | 41 | | |
39 | 42 | | |
40 | | - | |
41 | | - | |
| 43 | + | |
| 44 | + | |
42 | 45 | | |
43 | | - | |
| 46 | + | |
44 | 47 | | |
45 | | - | |
| 48 | + | |
46 | 49 | | |
47 | 50 | | |
48 | 51 | | |
49 | 52 | | |
50 | 53 | | |
51 | 54 | | |
52 | 55 | | |
53 | | - | |
54 | | - | |
| 56 | + | |
| 57 | + | |
55 | 58 | | |
56 | | - | |
| 59 | + | |
57 | 60 | | |
58 | | - | |
| 61 | + | |
59 | 62 | | |
60 | 63 | | |
61 | 64 | | |
| |||
64 | 67 | | |
65 | 68 | | |
66 | 69 | | |
67 | | - | |
68 | | - | |
| 70 | + | |
| 71 | + | |
69 | 72 | | |
70 | 73 | | |
71 | 74 | | |
| |||
74 | 77 | | |
75 | 78 | | |
76 | 79 | | |
77 | | - | |
| 80 | + | |
78 | 81 | | |
79 | 82 | | |
80 | 83 | | |
| |||
86 | 89 | | |
87 | 90 | | |
88 | 91 | | |
89 | | - | |
| 92 | + | |
90 | 93 | | |
91 | 94 | | |
92 | 95 | | |
| |||
99 | 102 | | |
100 | 103 | | |
101 | 104 | | |
102 | | - | |
| 105 | + | |
103 | 106 | | |
104 | 107 | | |
105 | 108 | | |
106 | | - | |
| 109 | + | |
107 | 110 | | |
108 | 111 | | |
109 | 112 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
| 41 | + | |
| 42 | + | |
41 | 43 | | |
42 | 44 | | |
43 | 45 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
403 | 403 | | |
404 | 404 | | |
405 | 405 | | |
406 | | - | |
407 | | - | |
408 | 406 | | |
409 | | - | |
| 407 | + | |
410 | 408 | | |
411 | 409 | | |
412 | 410 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1151 | 1151 | | |
1152 | 1152 | | |
1153 | 1153 | | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
| 1189 | + | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
| 1225 | + | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + | |
| 1229 | + | |
| 1230 | + | |
| 1231 | + | |
| 1232 | + | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
| 1236 | + | |
| 1237 | + | |
| 1238 | + | |
| 1239 | + | |
| 1240 | + | |
| 1241 | + | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
| 1250 | + | |
| 1251 | + | |
| 1252 | + | |
| 1253 | + | |
| 1254 | + | |
1154 | 1255 | | |
1155 | 1256 | | |
1156 | 1257 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
30 | | - | |
31 | | - | |
| 29 | + | |
| 30 | + | |
32 | 31 | | |
33 | 32 | | |
34 | 33 | | |
| |||
0 commit comments