Instead of calling pushKV(hash, info)
, which incurs in duplicate key checks, call __pushKV
which (currently) doesn’t.
Improves RPC getrawmempool
and REST /rest/mempool/contents.json
.
Fixes #14765.
mempool with 100k transactions:
Before:
0time bitcoin-cli -regtest getrawmempool true > /dev/null
1bitcoin-cli -regtest getrawmempool true > /dev/null 3.75s user 0.90s system 8% cpu 52.170 total
After:
0time bitcoin-cli -regtest getrawmempool true > /dev/null
1bitcoin-cli -regtest getrawmempool true > /dev/null 3.43s user 0.73s system 45% cpu 9.174 total
I guess you could duplicate one of the benchmarks
Can you point me in the right direction?
or write a functional test.
What should I test?
__pushKV
instead.
__
because it does not check the type of target, which is set properly here.
__pushKV
was added in https://github.com/jgarzik/univalue/commit/ceb1194137421afba01e8c1042bf75f3a2cdddc3.
Looks like it could be either private or have another name. I don’t have strong preference as the goal is to avoid the duplicate key check, but I’m more inclined to not use the “internal/private/reserved” method.
OTOH it would be reasonable to add duplicate key checks to pushKVs
and then we would have a performance regression.
Maybe we should rename __pushKV
to pushKVUnchecked
?
465@@ -466,7 +466,10 @@ UniValue mempoolToJSON(bool fVerbose)
466 const uint256& hash = e.GetTx().GetHash();
467 UniValue info(UniValue::VOBJ);
468 entryToJSON(info, e);
469- o.pushKV(hash.ToString(), info);
470+ UniValue entry(UniValue::VOBJ);
471+ entry.pushKV(hash.ToString(), info);
472+ // `pushKVs` is used to avoid duplicate key check in `pushKV`
0 // pushKVs is used to avoid duplicate key check in pushKV
1 // It is safe to use because ::mempool.mapTx is a set without duplicates
@MarcoFalke not sure about the benchmark. This is a small change to fix the original issue. But I think univalue should have an official API to avoid duplicate key checks and so the benchmark should be there, or am I wrong?
Pushed with your suggestion.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
No conflicts as of last run.
Co-Authored-By: MarcoFalke <falke.marco@gmail.com>
UniValue::__pushKV
and adjusted the comment.
I’ve seen this PR a bit late (just after it got merged), but fwiw here is some real world improvement data:
Time it takes to GET /rest/mempool/contents.json
(querys over a minute apart):
in v0.18.0 :
057.9s for 59474 unconfirmed Transactions (36.11 MB)
148.7s for 60199 unconfirmed Transactions (37.02 MB)
259.2s for 55544 unconfirmed Transactions (36.14 MB)
345.5s for 55464 unconfirmed Transactions (35.45 MB)
4avg. of 52.8s
v0.18.0 with the proposed change:
035.8s for 54308 unconfirmed Transactions (34.94 MB)
140.4s for 55065 unconfirmed Transactions (35.17 MB)
237.0s for 55914 unconfirmed Transactions (35.47 MB)
333.4s for 56739 unconfirmed Transactions (35.73 MB)
4avg. of 36.6s
Which for my sample is a reduction of 16.2s or 30%!! :tada:
promag
Empact
MarcoFalke
DrahtBot
0xB10C
fanquake
Labels
RPC/REST/ZMQ
Resource usage
Milestone
0.19.0