Skip to content

Commit eb13718

Browse files
committed
Merge bitcoin/bitcoin#31179: RPC: Add reserve member function to UniValue and use it in blockToJSON function
5d82d92 rpc: reserve space for `UniValue` variables in `blockToJSON` (ismaelsadeeq) 6a506d5 UniValue: add reserve member function (ismaelsadeeq) bd46119 bench: support benching all verbosity of `BlockToJson` (ismaelsadeeq) Pull request description: This PR is motivated by bitcoin/bitcoin#30495 (comment), It adds a `reserve` member function to `UniValue` and applies it within the `blockToJSON` function to pre-allocate memory, minimizing reallocation's. <details> <summary>Slight performance increase in verbosity 1</summary> On **master**: | ns/op | op/s | err% | total | benchmark | |--------------:|------------:|------:|------:|:------------------------| | 190,342 | 5,254 | 2.3% | 0.01 | `BlockToJsonVerbose1` | | 34,812,292 | 28.73 | 1.0% | 0.38 | `BlockToJsonVerbose2` | | 34,457,167 | 29.02 | 1.0% | 0.38 | `BlockToJsonVerbose3` | On **this PR**: | ns/op | op/s | err% | total | benchmark | |--------------:|------------:|------:|------:|:------------------------| | 172,278 | 5,805 | 0.7% | 0.01 | `BlockToJsonVerbose1` | | 33,720,584 | 29.66 | 0.4% | 0.37 | `BlockToJsonVerbose2` | | 33,884,417 | 29.51 | 1.2% | 0.38 | `BlockToJsonVerbose3` | </details> ACKs for top commit: maflcko: review ACK 5d82d92 🐀 l0rinc: ACK 5d82d92 achow101: ACK 5d82d92 Eunovo: Re-ACK bitcoin/bitcoin@5d82d92 Tree-SHA512: bdd2c1bcdc4d060d30ad3be0b10f0d722dda0c2286bc4156af851503220e8854e76a4dc53456826b543c110982455268838172d3a1026eee754d4c673b48ea05
2 parents 73e754b + 5d82d92 commit eb13718

File tree

5 files changed

+33
-3
lines changed

5 files changed

+33
-3
lines changed

src/bench/rpc_blockchain.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,34 @@ struct TestBlockAndIndex {
4545

4646
} // namespace
4747

48-
static void BlockToJsonVerbose(benchmark::Bench& bench)
48+
static void BlockToJson(benchmark::Bench& bench, TxVerbosity verbosity)
4949
{
5050
TestBlockAndIndex data;
5151
const uint256 pow_limit{data.testing_setup->m_node.chainman->GetParams().GetConsensus().powLimit};
5252
bench.run([&] {
53-
auto univalue = blockToJSON(data.testing_setup->m_node.chainman->m_blockman, data.block, data.blockindex, data.blockindex, TxVerbosity::SHOW_DETAILS_AND_PREVOUT, pow_limit);
53+
auto univalue = blockToJSON(data.testing_setup->m_node.chainman->m_blockman, data.block, data.blockindex, data.blockindex, verbosity, pow_limit);
5454
ankerl::nanobench::doNotOptimizeAway(univalue);
5555
});
5656
}
5757

58-
BENCHMARK(BlockToJsonVerbose, benchmark::PriorityLevel::HIGH);
58+
static void BlockToJsonVerbosity1(benchmark::Bench& bench)
59+
{
60+
BlockToJson(bench, TxVerbosity::SHOW_TXID);
61+
}
62+
63+
static void BlockToJsonVerbosity2(benchmark::Bench& bench)
64+
{
65+
BlockToJson(bench, TxVerbosity::SHOW_DETAILS);
66+
}
67+
68+
static void BlockToJsonVerbosity3(benchmark::Bench& bench)
69+
{
70+
BlockToJson(bench, TxVerbosity::SHOW_DETAILS_AND_PREVOUT);
71+
}
72+
73+
BENCHMARK(BlockToJsonVerbosity1, benchmark::PriorityLevel::HIGH);
74+
BENCHMARK(BlockToJsonVerbosity2, benchmark::PriorityLevel::HIGH);
75+
BENCHMARK(BlockToJsonVerbosity3, benchmark::PriorityLevel::HIGH);
5976

6077
static void BlockToJsonVerboseWrite(benchmark::Bench& bench)
6178
{

src/core_write.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry
181181
entry.pushKV("locktime", (int64_t)tx.nLockTime);
182182

183183
UniValue vin{UniValue::VARR};
184+
vin.reserve(tx.vin.size());
184185

185186
// If available, use Undo data to calculate the fee. Note that txundo == nullptr
186187
// for coinbase transactions and for transactions where undo data is unavailable.
@@ -203,6 +204,7 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry
203204
}
204205
if (!tx.vin[i].scriptWitness.IsNull()) {
205206
UniValue txinwitness(UniValue::VARR);
207+
txinwitness.reserve(tx.vin[i].scriptWitness.stack.size());
206208
for (const auto& item : tx.vin[i].scriptWitness.stack) {
207209
txinwitness.push_back(HexStr(item));
208210
}
@@ -232,6 +234,7 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry
232234
entry.pushKV("vin", std::move(vin));
233235

234236
UniValue vout(UniValue::VARR);
237+
vout.reserve(tx.vout.size());
235238
for (unsigned int i = 0; i < tx.vout.size(); i++) {
236239
const CTxOut& txout = tx.vout[i];
237240

src/rpc/blockchain.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIn
186186
result.pushKV("size", (int)::GetSerializeSize(TX_WITH_WITNESS(block)));
187187
result.pushKV("weight", (int)::GetBlockWeight(block));
188188
UniValue txs(UniValue::VARR);
189+
txs.reserve(block.vtx.size());
189190

190191
switch (verbosity) {
191192
case TxVerbosity::SHOW_TXID:

src/univalue/include/univalue.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class UniValue {
7070

7171
size_t size() const { return values.size(); }
7272

73+
void reserve(size_t new_cap);
74+
7375
void getObjMap(std::map<std::string,UniValue>& kv) const;
7476
bool checkObject(const std::map<std::string,UniValue::VType>& memberTypes) const;
7577
const UniValue& operator[](const std::string& key) const;

src/univalue/lib/univalue.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,10 @@ const UniValue& UniValue::find_value(std::string_view key) const
240240
return NullUniValue;
241241
}
242242

243+
void UniValue::reserve(size_t new_cap)
244+
{
245+
values.reserve(new_cap);
246+
if (typ == VOBJ) {
247+
keys.reserve(new_cap);
248+
}
249+
}

0 commit comments

Comments
 (0)