rpc: Reduce Univalue push_backV peak memory usage in listtransactions#25464
Hidden character warning
rpc: Reduce Univalue push_backV peak memory usage in listtransactions#25464fanquake merged 1 commit intobitcoin:masterfrom
Conversation
There was a problem hiding this comment.
Code Review ACK fa8a1c0
I agree with the changes done in this PR. To explain my understanding and the reason for my approval of this PR, I would reiterate the changes done in it as I understood them.
Reasoning:
I was able to confirm that there were three locations where the same data was being stored:
- In the
UniValue retvariable In theMemory consumed in creating a temporary vector to input intotxsvector created to storeret.getValues()push_backVfunction- In the
valuesofUniValue result.
This PR changes the storing of the values only once by:
- Creating a new function,
push_backV, which, instead of taking the whole vector as an argument, only takes the first and last iterators, saving up on creating a memory-consuming temporary variable. - Instead of copying the values, moves them by directly using their locations in the memory to store the values in the
resultvariable.
This change allows using 1/3rd of the memory to achieve the same functionality. And removing the need to create variables and copying the values would also provide a minor speed boost.
Edit: Thanks, @MarcoFalke, for helping clear up the misunderstood points!
This is not accurate. The memory used by Memory is consumed when creating an unnamed temporary vector, to be passed into |
|
While the massif chart may not be accurate, the maximum memory usage should be. I've also confirmed this with Results for master:
This pull:
Thus, in my testing, the changes in this pull both speed-up and reduce memory. |
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
|
cc @martinus |
martinus
left a comment
There was a problem hiding this comment.
Code review ACK, looks good to me!
| */ | ||
| static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) | ||
| template <class Vec> | ||
| static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong, Vec& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) |
There was a problem hiding this comment.
In line 368 and 409 you could use ret.push_back(std::move(entry)); to safe another copy
There was a problem hiding this comment.
Good point, but I don't think this affects the peak memory, so can be done in the follow-up #25429
…e in listtransactions fa8a1c0 rpc: Fix Univalue push_backV OOM in listtransactions (MacroFake) Pull request description: Related to, but not intended as a fix for bitcoin#25229. Currently the RPC will have the same data stored thrice: * `UniValue ret` (memory filled by `ListTransactions`) * `std::vector<UniValue> vec` (constructed by calling `push_backV`) * `UniValue result` (the actual result, memory filled by `push_backV`) Fix this by filling the memory only once: * `std::vector<UniValue> ret` (memory filled by `ListTransactions`) * Pass iterators to `push_backV` instead of creating a full copy * Move memory into `UniValue result` instead of copying it ACKs for top commit: shaavan: Code Review ACK fa8a1c0 Tree-SHA512: 1c3ca40fc8497134a4141195160e4aa9fe72b3c00c5998c972b58ad0eb498ebea05013f9105bb80e7264c9db1d0e7a2032396a8a4af1f326d831fbee20f32ea3


Related to, but not intended as a fix for #25229.
Currently the RPC will have the same data stored thrice:
UniValue ret(memory filled byListTransactions)std::vector<UniValue> vec(constructed by callingpush_backV)UniValue result(the actual result, memory filled bypush_backV)Fix this by filling the memory only once:
std::vector<UniValue> ret(memory filled byListTransactions)push_backVinstead of creating a full copyUniValue resultinstead of copying it