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
rpc: move UniValue in blockToJSON #30094
Conversation
Without explicitly declaring the move, these UniValues get copied, causing increased memory usage. Fix this by explicitly moving the UniValue objects. Used by `rest_block` and `getblock` RPC.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. |
review ACK b77bad3 |
Also "fixes" #30052 |
Unrelated to the blockToJSON changes here, as a follow-up, it may be possible to "fix" #25229 in the same way? |
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.
ACK b77bad3
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.
ACK b77bad3
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 b77bad3
Actually, looks like this could use a |
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.
ACK b77bad3, I have reviewed the code and it looks OK.
I would be great to check all UniValue::push_back
and UniValue::pushKV
invocations in the codebase.
Without explicitly declaring the move, these UniValues get copied, causing increased memory usage. Fix this by explicitly moving the UniValue objects. Used by `rest_block` and `getblock` RPC. Github-Pull: bitcoin#30094 Rebased-From: b77bad3
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.
ACK b77bad3
I can push a similar commit here if it's worth merging the two. Or open a separate PR? Perhaps with 3 ACKs a separate PR is preferable? I also am only halfway through making a "big wallet" (using achow101's make-big-wallet script, so I have no suitable wallet to test such a commit against currently.
I don't see
I can check the remainder of the codebase for other occurrences too. |
Whoops, of course you're right. It probably should though :) |
I was already working on this and... wow. You've opened a big can of worms here @willcl-ark :). But that's a good thing because it should reduce memusage and increase performance I'd assume. See here for my first pass. It's a beast. https://github.com/theuni/bitcoin/commits/less-univalue-copies/ The first commit mostly just does the naive thing of adding The second commit adds These are changes required for bitcoind only. I haven't done tests/fuzz/bench/etc. To flesh them out, I changed the function signatures of the corresponding UniValue functions to accept rvalues only. Edit: added 2 more commits to avoid copying strings. @willcl-ark let me know if you've already been working on this some and how you'd like to collaborate on it. There's quite a bit of work to do here :) |
Without explicitly declaring the move, these UniValues get copied, causing increased memory usage. Fix this by explicitly moving the UniValue objects. Used by `rest_block` and `getblock` RPC. Github-Pull: bitcoin#30094 Rebased-From: b77bad3
Backported to 27.x in #30092. |
Without explicitly declaring the move, these UniValues get copied, causing increased memory usage. Fix this by explicitly moving the UniValue objects. Used by `rest_block` and `getblock` RPC. Github-Pull: bitcoin#30094 Rebased-From: b77bad3
Wow! This looks like a great start! Will begin to review...
I have not yet started to look at this so will avoid duplicating the effort! All I had started was a branch to add explicit move semantics (which it turns out is not needed): master...willcl-ark:bitcoin:univalue-move Happy to collaborate though if you have any specific things in mind you'd like help with :) I do have a somewhat-reproducible benchmark set up for this specifc REST call, it's just querying every 5000th block. I was also using @achow101 's make-big-wallet to make a big wallet last night (wow-- it took 12 hours to generate!) in order to try and benchmark the I don't think it's strictly needed, as moving a large UniValue is almost certainly an improvement over a large copy, but I still like to see for myself. |
@theuni FWIW I do see some increased RSS measurements on your current branch vs master (with my one, single test using listtransactions rpc on a large wallet): This is also what I saw on my linked "univalue-move" branch above. I didn't investigate why exactly this happens, yet. It seems like |
backport for 26.x in #29899 |
@willcl-ark Thanks! Huh, I can't think of any reason why that would be the case. Saving on copies should be nothing but a win. Odd. I think I'll start by opening a PR for the simplest/most obvious moves. Maybe you could help me bench those? |
@willcl-ark I added a quick/dirty bench to my branch that shows the difference between copies and moves. It seems correct to me. Do you have any interest in doing the same for memory usage, just as a sanity check that nothing funky is happening low-level? Beyond that, I'm not really sure where to start with your graph... it really doesn't make any sense to me :) |
You benchmark looks good and reports the result I'd expect too! I'll investigate my own measurements some more in the mean time... |
d7707d9 rpc: avoid copying into UniValue (Cory Fields) Pull request description: These are the simple (and hopefully obviously correct) copies that can be moves instead. This is a follow-up from #30094 (comment) As it turns out, there are hundreds of places where we copy UniValues needlessly. It should be the case that moves are always preferred over copies, so there should be no downside to these changes. willcl-ark, however, noticed that memory usage may increase in some cases. Logically this makes no sense to me. The only plausible explanation imo is that because the moves are faster, more ops/second occur in some cases. This list of moves was obtained by changing the function signatures of the UniValue functions to accept only rvalues, then compiling and fixing them up one by one. There still exist many places where copies are being made. These can/should be fixed up, but weren't done here for the sake of doing the easy ones first. I ran these changes through clang-tidy with `performance-move-const-arg` and `bugprone-use-after-move` and no bugs were detected (though that's obviously not to say it can be trusted 100%). As stated above, there are still lots of other less trivial fixups to do after these including: - Using non-const UniValues where possible so that moves can happen - Refactoring code in order to be able to move a UniValue without introducing a use-after-move - Refactoring functions to accept UniValues by value rather than by const reference ACKs for top commit: achow101: ACK d7707d9 ryanofsky: Code review ACK d7707d9. No changes since last review other than rebase. I agree benchmarks showing increased peak memory usage and RSS are surprising, but number of allocations is down as expected, and runtime is also decreased. willcl-ark: ACK d7707d9 Tree-SHA512: 7f511be73984553c278186286a7d161a34b2574c7f5f1a0edc87c2913b4c025a0af5241ef9af2df17547f2e4ef79710aa5bbb762fc9472435781c0488dba3435
Without explicitly declaring the move, these UniValues get copied, causing increased memory usage. Fix this by explicitly moving the UniValue objects. Used by `rest_block` and `getblock` RPC. Github-Pull: bitcoin#30094 Rebased-From: b77bad3
Fixes: #24542
Fixes: #30052
Without explicitly declaring the move, these
UniValues
get copied, causing increased memory usage. Fix this by explicitly moving theUniValue
objects.Used by
rest_block
andgetblock
RPC.