-
Notifications
You must be signed in to change notification settings - Fork 37.7k
rpc: Reduce Univalue push_backV peak memory usage in listtransactions #25464
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
The head ref may contain hidden characters: "2206-univalue-oom-\u{1F6C3}"
Conversation
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.
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 ret
variable In theMemory consumed in creating a temporary vector to input intotxs
vector created to storeret.getValues()
push_backV
function- In the
values
ofUniValue 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
result
variable.
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 |
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.
Code review ACK, looks good to me!
* @param filter_ismine The "is mine" filter flags. | ||
* @param filter_label Optional label string to filter incoming transactions. | ||
*/ | ||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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_backV
instead of creating a full copyUniValue result
instead of copying it