I was running some benchmarks on 20MB blocks, and was surprised at how long block validation took even when all transactions had already been seen and were in the signature cache.
So I moved caching up from being a low-level signature cache to a high-level “have we already validated this txid.”
Benchmark results on a recent 365K block with all transactions already in the memory pool / signature cache:
Old code: (results from running with -debug=bench and hacked code to make sure all txn pre-validated): - Verify 1839 txins: 191.66ms (0.104ms/txin) New code: - Verify 1839 txins: 2.06ms (0.001ms/txin)
Extrapolating to full (1MB) blocks, the old code would spend about 600ms CPU time per hop propagating blocks with already-seen transactions, this new code will spend under 10ms.
Memory usage is about 60 times smaller, also: Old code: (sizeof(scriptSig)+std::set overhead) * number of txins (about 200K for the 365K block) New code: an extra 4 bytes per transaction in the mempool (about 3K for the 365K block)
I first wrote this as a standalone CTxValidationCache class, but it is simpler and more efficient to extend the mempool. The second commit in this pull request fixes two bugs in limitedmap I stumbled across when testing that code.
REBASED to keep the old signature cache (see discussion below)