-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Cache witness hash in CTransaction #13011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
ryanofsky
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK fae63d51ab252579adbaceb6aaba935bae75de88. Code looks ok, but what's the motivation for this change? I imagine there are a lot of performance implications.
Also, why is unique_ptr<uint256> used for the witness hash when the plain hash is just uint256?
src/primitives/transaction.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could use MakeUnique<const uint256>(SerializeHash(*this, SER_GETHASH, 0)); here
src/primitives/transaction.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you could remove some of the boilerplate and repetition here using member initialization in the header:
const std::unique_ptr<const uint256> m_witness_hash = ComputeWitnessHash();
It would be nice to do this for the other members, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder what would be the execution order in this case? ComputeWitnessHash calls SerializeHash(*this, ...) so other members must be initialized before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder what would be the execution order in this case? ComputeWitnessHash calls SerializeHash(*this, ...) so other members must be initialized before.
Execution order always the matches order members are declared in the class, not the order initializations are written in the constructor (compilers will warn if the orders differ), so this wouldn't change behavior. You can see https://isocpp.org/wiki/faq/ctors#ctor-initializer-order for discussion about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We couldn't do the same for the hash member, I guess, so will leave this as is for now.
promag
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK.
I guess the extra memory usage is neglectable.
src/primitives/transaction.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this expression be in ComputeWitnessHash?
|
Concept ACK |
|
Honestly I think we need to revive #9700. Now that SegWit has some use, giving up on the huge performance gains of that (and this) for (IMO) minor design concerns is an absurd tradeoff. |
|
Then at the very least introduce alternate versions of CTransaction/CBlock that don't precompute anything, for use in reindexing and rescanning and serving blocks from disk. Otherwise you'll waste your time computing wtxids/sighashes in those cases, where they're never used. |
|
Indeed, though we may want to look into something wholesale smarter for rescan, its already impossibly slow even when considering the amount of I/O required. |
fae63d5 to
fa77996
Compare
Silently converting to a CMutableTransaction will drop all caches and should thus be done explicitly
fa77996 to
fac1223
Compare
|
Split into two commits for easier review |
|
utACK fac1223 Numbers would be nice, but the code looks good. |
|
Was a discussion about this in IRC meeting yesterday: https://botbot.me/freenode/bitcoin-core-dev/msg/99929243/ Beginning of discussion before it goes on to talk about related PRs like #13098
|
|
This speeds up:
This presumably slows down rescan, which uses a |
|
Note: You can run benchmarks such as: |
|
If performance is a concern in contexts where the precomputed value isn't needed, couldn't this just lazily compute and cache the witness hash? There'd probably have to be some concurrency handling, I suppose. |
|
avoid "some concurrency handling" was the reason for making these fields const in the first place. The alternative is either indirections (through atomic pointers) or mutexes all over the place. The solution to not computing it in places where it isn't needed is not using a type that caches these values. |
|
utACK fac1223. |
|
utACK fac1223 |
ryanofsky
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK fac1223. Only change since previous review is making m_witness_hash member const uint256 instead of std::unique_ptr<const uint256>, and adding the new cleanup commit: "Make CMutableTransaction constructor explicit …"
|
utACK fac1223 |
|
utACK fac1223 |
|
utACK fac1223 |
fac1223 Cache witness hash in CTransaction (MarcoFalke) faab55f Make CMutableTransaction constructor explicit (MarcoFalke) Pull request description: This speeds up: * compactblocks (v2) * ATMP * validation and miner (via `BlockWitnessMerkleRoot`) * sigcache (see also unrelated #13204) * rpc and rest (nice, but irrelevant) This presumably slows down rescan, which uses a `CTransaction` and its `GetHash`, but never uses the `GetWitnessHash`. The slow down is proportional to the number of witness transactions in the rescan window. I.e. early in the chain there should be no measurable slow down. Later in the chain, there should be a slow down, but acceptable given the speedups in the modules mentioned above. Tree-SHA512: 443e86acfcceb5af2163e68840c581d44159af3fd1fce266cab3504b29fcd74c50812b69a00d41582e7e1c5ea292f420ce5e892cdfab691da9c24ed1c44536c7
fac1223 Cache witness hash in CTransaction (MarcoFalke) faab55f Make CMutableTransaction constructor explicit (MarcoFalke) Pull request description: This speeds up: * compactblocks (v2) * ATMP * validation and miner (via `BlockWitnessMerkleRoot`) * sigcache (see also unrelated bitcoin#13204) * rpc and rest (nice, but irrelevant) This presumably slows down rescan, which uses a `CTransaction` and its `GetHash`, but never uses the `GetWitnessHash`. The slow down is proportional to the number of witness transactions in the rescan window. I.e. early in the chain there should be no measurable slow down. Later in the chain, there should be a slow down, but acceptable given the speedups in the modules mentioned above. Tree-SHA512: 443e86acfcceb5af2163e68840c581d44159af3fd1fce266cab3504b29fcd74c50812b69a00d41582e7e1c5ea292f420ce5e892cdfab691da9c24ed1c44536c7
This speeds up:
BlockWitnessMerkleRoot)This presumably slows down rescan, which uses a
CTransactionand itsGetHash, but never uses theGetWitnessHash. The slow down is proportional to the number of witness transactions in the rescan window. I.e. early in the chain there should be no measurable slow down. Later in the chain, there should be a slow down, but acceptable given the speedups in the modules mentioned above.