From 544823b27295b8bb78f8f18d4240087da0c769aa Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sat, 23 Feb 2019 11:04:20 -0500 Subject: [PATCH] merge bitcoin#15473: bench: Benchmark MempoolToJSON --- src/Makefile.bench.include | 5 +++- src/bench/rpc_mempool.cpp | 42 +++++++++++++++++++++++++++++++++ src/rest.cpp | 4 ++-- src/rpc/blockchain.cpp | 48 +++++++++++++++++--------------------- src/rpc/blockchain.h | 5 ++-- src/txmempool.cpp | 2 +- src/txmempool.h | 4 ++-- 7 files changed, 76 insertions(+), 34 deletions(-) create mode 100644 src/bench/rpc_mempool.cpp diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 678574ddfa..bdeafb3226 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -34,6 +34,7 @@ bench_bench_dash_SOURCES = \ bench/mempool_eviction.cpp \ bench/nanobench.h \ bench/nanobench.cpp \ + bench/rpc_mempool.cpp \ bench/util_time.cpp \ bench/base58.cpp \ bench/bech32.cpp \ @@ -58,7 +59,9 @@ bench_bench_dash_LDADD = \ $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) \ $(LIBSECP256K1) \ - $(LIBUNIVALUE) + $(LIBUNIVALUE) \ + $(EVENT_PTHREADS_LIBS) \ + $(EVENT_LIBS) if ENABLE_ZMQ bench_bench_dash_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp new file mode 100644 index 0000000000..fa365af1a6 --- /dev/null +++ b/src/bench/rpc_mempool.cpp @@ -0,0 +1,42 @@ +// Copyright (c) 2011-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include + +#include + +#include +#include + +static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) +{ + LockPoints lp; + pool.addUnchecked(CTxMemPoolEntry(tx, fee, /* time */ 0, /* height */ 1, /* spendsCoinbase */ false, /* sigOpCost */ 4, lp)); +} + +static void RpcMempool(benchmark::Bench& bench) +{ + CTxMemPool pool; + LOCK2(cs_main, pool.cs); + + for (int i = 0; i < 1000; ++i) { + CMutableTransaction tx = CMutableTransaction(); + tx.vin.resize(1); + tx.vin[0].scriptSig = CScript() << OP_1; + tx.vout.resize(1); + tx.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; + tx.vout[0].nValue = i; + const CTransactionRef tx_r{MakeTransactionRef(tx)}; + AddTx(tx_r, /* fee */ i, pool); + } + + bench.minEpochIterations(40).run([&] { + (void)MempoolToJSON(pool, /*verbose*/ true); + }); +} + +BENCHMARK(RpcMempool); diff --git a/src/rest.cpp b/src/rest.cpp index 8614d56ac1..68cbf8d190 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -295,7 +295,7 @@ static bool rest_mempool_info(HTTPRequest* req, const std::string& strURIPart) switch (rf) { case RetFormat::JSON: { - UniValue mempoolInfoObject = mempoolInfoToJSON(); + UniValue mempoolInfoObject = MempoolInfoToJSON(::mempool); std::string strJSON = mempoolInfoObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); @@ -317,7 +317,7 @@ static bool rest_mempool_contents(HTTPRequest* req, const std::string& strURIPar switch (rf) { case RetFormat::JSON: { - UniValue mempoolObject = mempoolToJSON(true); + UniValue mempoolObject = MempoolToJSON(::mempool, true); std::string strJSON = mempoolObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 492800a8e0..eb695face0 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -465,9 +465,9 @@ static std::string EntryDescriptionString() " \"instantlock\" : true|false (boolean) True if this transaction was locked via InstantSend\n"; } -static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs) +static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs) { - AssertLockHeld(mempool.cs); + AssertLockHeld(pool.cs); UniValue fees(UniValue::VOBJ); fees.pushKV("base", ValueFromAmount(e.GetFee())); @@ -491,7 +491,7 @@ static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCK std::set setDepends; for (const CTxIn& txin : tx.vin) { - if (mempool.exists(txin.prevout.hash)) + if (pool.exists(txin.prevout.hash)) setDepends.insert(txin.prevout.hash.ToString()); } @@ -504,8 +504,8 @@ static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCK info.pushKV("depends", depends); UniValue spent(UniValue::VARR); - const CTxMemPool::txiter &it = mempool.mapTx.find(tx.GetHash()); - const CTxMemPool::setEntries &setChildren = mempool.GetMemPoolChildren(it); + const CTxMemPool::txiter& it = pool.mapTx.find(tx.GetHash()); + const CTxMemPool::setEntries& setChildren = pool.GetMemPoolChildren(it); for (CTxMemPool::txiter childiter : setChildren) { spent.push_back(childiter->GetTx().GetHash().ToString()); } @@ -514,28 +514,24 @@ static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCK info.pushKV("instantlock", llmq::quorumInstantSendManager->IsLocked(tx.GetHash())); } -UniValue mempoolToJSON(bool fVerbose) +UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose) { - if (fVerbose) - { - LOCK(mempool.cs); + if (verbose) { + LOCK(pool.cs); UniValue o(UniValue::VOBJ); - for (const CTxMemPoolEntry& e : mempool.mapTx) - { + for (const CTxMemPoolEntry& e : pool.mapTx) { const uint256& hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - entryToJSON(info, e); + entryToJSON(pool, info, e); // Mempool has unique entries so there is no advantage in using // UniValue::pushKV, which checks if the key already exists in O(N). // UniValue::__pushKV is used instead which currently is O(1). o.__pushKV(hash.ToString(), info); } return o; - } - else - { + } else { std::vector vtxid; - mempool.queryHashes(vtxid); + pool.queryHashes(vtxid); UniValue a(UniValue::VARR); for (const uint256& hash : vtxid) @@ -578,7 +574,7 @@ static UniValue getrawmempool(const JSONRPCRequest& request) if (!request.params[0].isNull()) fVerbose = request.params[0].get_bool(); - return mempoolToJSON(fVerbose); + return MempoolToJSON(::mempool, fVerbose); } static UniValue getmempoolancestors(const JSONRPCRequest& request) @@ -643,7 +639,7 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request) const CTxMemPoolEntry &e = *ancestorIt; const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - entryToJSON(info, e); + entryToJSON(::mempool, info, e); o.pushKV(_hash.ToString(), info); } return o; @@ -712,7 +708,7 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request) const CTxMemPoolEntry &e = *descendantIt; const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - entryToJSON(info, e); + entryToJSON(::mempool, info, e); o.pushKV(_hash.ToString(), info); } return o; @@ -752,7 +748,7 @@ static UniValue getmempoolentry(const JSONRPCRequest& request) const CTxMemPoolEntry &e = *it; UniValue info(UniValue::VOBJ); - entryToJSON(info, e); + entryToJSON(::mempool, info, e); return info; } @@ -1731,15 +1727,15 @@ static UniValue getchaintips(const JSONRPCRequest& request) return res; } -UniValue mempoolInfoToJSON() +UniValue MempoolInfoToJSON(const CTxMemPool& pool) { UniValue ret(UniValue::VOBJ); - ret.pushKV("size", (int64_t) mempool.size()); - ret.pushKV("bytes", (int64_t) mempool.GetTotalTxSize()); - ret.pushKV("usage", (int64_t) mempool.DynamicMemoryUsage()); + ret.pushKV("size", (int64_t)pool.size()); + ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize()); + ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage()); size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; ret.pushKV("maxmempool", (int64_t) maxmempool); - ret.pushKV("mempoolminfee", ValueFromAmount(std::max(mempool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK())); + ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK())); ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())); ret.pushKV("instantsendlocks", (int64_t)llmq::quorumInstantSendManager->GetInstantSendLockCount()); @@ -1768,7 +1764,7 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request) + HelpExampleRpc("getmempoolinfo", "") ); - return mempoolInfoToJSON(); + return MempoolInfoToJSON(::mempool); } static UniValue preciousblock(const JSONRPCRequest& request) diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h index 275fde32c5..701be69067 100644 --- a/src/rpc/blockchain.h +++ b/src/rpc/blockchain.h @@ -11,6 +11,7 @@ class CBlock; class CBlockIndex; +class CTxMemPool; class UniValue; static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5; @@ -30,10 +31,10 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex *); UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails = false); /** Mempool information to JSON */ -UniValue mempoolInfoToJSON(); +UniValue MempoolInfoToJSON(const CTxMemPool& pool); /** Mempool to JSON */ -UniValue mempoolToJSON(bool fVerbose = false); +UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose = false); /** Block header to JSON */ UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index aef5c81be4..0fa17a8e9f 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1183,7 +1183,7 @@ std::vector CTxMemPool::Get return iters; } -void CTxMemPool::queryHashes(std::vector& vtxid) +void CTxMemPool::queryHashes(std::vector& vtxid) const { LOCK(cs); auto iters = GetSortedDepthAndScore(); diff --git a/src/txmempool.h b/src/txmempool.h index 98ba46ce93..9a1a75409c 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -192,7 +192,7 @@ private: const LockPoints& lp; }; -// extracts a transaction hash from CTxMempoolEntry or CTransactionRef +// extracts a transaction hash from CTxMemPoolEntry or CTransactionRef struct mempoolentry_txid { typedef uint256 result_type; @@ -629,7 +629,7 @@ public: void clear(); void _clear() EXCLUSIVE_LOCKS_REQUIRED(cs); //lock free bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb); - void queryHashes(std::vector& vtxid); + void queryHashes(std::vector& vtxid) const; bool isSpent(const COutPoint& outpoint) const; unsigned int GetTransactionsUpdated() const; void AddTransactionsUpdated(unsigned int n);