Bitcoin full node and query server

Feb 8, 2025

View in context in the libbitcoin Slack #general mirror.

evoskuil20:26
On the maxi I took another look at the performance analyzer during confirmation on the maxi. There are three concurrent loops for each block being confirmed: get-spends, is-spendable, is-spent. I previously spent a bunch of time organizing these in different groups with parallelism and without, and this was the most optimal. But still, the std lib loops are very inefficient. About 75% of all confirmation time on the maxi is spent in lock contention. The locks aren't guarding read/write - they are only providing thread synchronization for the loops. The database mutexes for hashmap headers, table allocators, and remap safety are all in place as well, but they are inconsequential - because there are very few writes occurring. So is appears that confirmation (absent thrashing) can be significantly optimized during IBD by performing more of the calculations concurrently by block (i.e. as part of validation) and using more storage (as we've done with the prevout table). The only aspect of confirmation that must be sequential by block is checking for spentness (i.e. query against the strong_tx table). So in theory we can produce an ordered list of tx ids to check for spentness by block, followed by writing spentness for each block.tx. Double spend checks are most expensive, as they require exhaustive search, however they rarely require a check for spentness, because double spends (duplicate tx storage or actual invalidity) are rare. So this is almost no storage and can be made concurrent (*). Confirmedness of prevouts just requires identifying all of the prevout tx pks and storing them until the confirmation stage. IOW, there would be a set of positive and negative tx pks checks for each block, which could just take the place of the data already stored into the prevout table, and would be the same size (4 bytes per spend), and would also be temporary (deletable). Given that we already use this temporary space and already cover the work distribution cost during validation, and that the concurrent part of confirmation would add no writes, it should be possible to significantly accelerate confirmation as long as the additional reads do not cause thrashing. Despite the fact that we read the entire block and previous outputs for validation, we never search the spend table. That's the big difference in terms of paging, as we must search for all spenders (even though we generally don't find any). But in the case of thrashing if this is run during validation, it could just be split out to an independent concurrent phase. So I think we can get much more concurrency out of confirmation.
👀 1