Changeset View
Changeset View
Standalone View
Standalone View
src/bench/chained_tx.cpp
Show First 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | static std::vector<CTransactionRef> twoInOneOutTree(const Config &config, | ||||
assert(chain.size() == txs); | assert(chain.size() == txs); | ||||
return chain; | return chain; | ||||
} | } | ||||
/// Run benchmark on AcceptToMemoryPool | /// Run benchmark on AcceptToMemoryPool | ||||
static void benchATMP(const Config &config, node::NodeContext &node, | static void benchATMP(const Config &config, node::NodeContext &node, | ||||
benchmark::Bench &bench, | benchmark::Bench &bench, | ||||
const std::vector<CTransactionRef> chainedTxs) { | const std::vector<CTransactionRef> chainedTxs) { | ||||
// ATMP uses gArgs, so we oblige | |||||
gArgs.ForceSetArg("-limitdescendantcount", ToString(chainedTxs.size())); | |||||
gArgs.ForceSetArg("-limitancestorcount", ToString(chainedTxs.size())); | |||||
gArgs.ForceSetArg("-limitancestorsize", ToString(chainedTxs.size() * 1000)); | |||||
gArgs.ForceSetArg("-limitdescendantsize", | |||||
ToString(chainedTxs.size() * 1000)); | |||||
auto chainman = Assert(node.chainman.get()); | auto chainman = Assert(node.chainman.get()); | ||||
Chainstate &activeChainState = chainman->ActiveChainstate(); | Chainstate &activeChainState = chainman->ActiveChainstate(); | ||||
CTxMemPool &mempool{*Assert(activeChainState.GetMempool())}; | CTxMemPool &mempool{*Assert(activeChainState.GetMempool())}; | ||||
assert(mempool.size() == 0); | assert(mempool.size() == 0); | ||||
// test with wellington latched (faster) | |||||
const bool wellingtonBefore = mempool.wellingtonLatched.exchange(true); | |||||
bench.run([&] { | bench.run([&] { | ||||
LOCK(::cs_main); | LOCK(::cs_main); | ||||
for (const auto &tx : chainedTxs) { | for (const auto &tx : chainedTxs) { | ||||
MempoolAcceptResult result = | MempoolAcceptResult result = | ||||
AcceptToMemoryPool(config, activeChainState, tx, GetTime(), | AcceptToMemoryPool(config, activeChainState, tx, GetTime(), | ||||
/*bypass_limits=*/false); | /*bypass_limits=*/false); | ||||
assert(result.m_result_type == | assert(result.m_result_type == | ||||
MempoolAcceptResult::ResultType::VALID); | MempoolAcceptResult::ResultType::VALID); | ||||
} | } | ||||
mempool.clear(); | mempool.clear(); | ||||
}); | }); | ||||
// restore state | |||||
mempool.wellingtonLatched = wellingtonBefore; | |||||
gArgs.ClearForcedArg("-limitdescendantcount"); | |||||
gArgs.ClearForcedArg("-limitancestorcount"); | |||||
gArgs.ClearForcedArg("-limitancestorsize"); | |||||
gArgs.ClearForcedArg("-limitdescendantsize"); | |||||
} | } | ||||
/// Run benchmark that reorganizes blocks with one-input-one-output transaction | /// Run benchmark that reorganizes blocks with one-input-one-output transaction | ||||
/// chains in them. | /// chains in them. | ||||
/// | /// | ||||
/// If 'includeMempoolTxRemoval' is set, the benchmark will include the time | /// If 'includeMempoolTxRemoval' is set, the benchmark will include the time | ||||
/// it takes to remove the transactions of re-connected blocks from the mempool. | /// it takes to remove the transactions of re-connected blocks from the mempool. | ||||
static void benchReorg(const Config &config, node::NodeContext &node, | static void benchReorg(const Config &config, node::NodeContext &node, | ||||
Show All 13 Lines | static void benchReorg(const Config &config, node::NodeContext &node, | ||||
CBlockIndex *tipBeforeInvalidate = activeChainState.m_chain.Tip(); | CBlockIndex *tipBeforeInvalidate = activeChainState.m_chain.Tip(); | ||||
assert(tipBeforeInvalidate != nullptr); | assert(tipBeforeInvalidate != nullptr); | ||||
CBlockIndex *blockToInvalidate = nullptr; | CBlockIndex *blockToInvalidate = nullptr; | ||||
CTxMemPool &mempool{*Assert(activeChainState.GetMempool())}; | CTxMemPool &mempool{*Assert(activeChainState.GetMempool())}; | ||||
assert(mempool.size() == 0); | assert(mempool.size() == 0); | ||||
// test with wellington latched (faster) | |||||
const bool wellingtonBefore = mempool.wellingtonLatched.exchange(true); | |||||
// Build blocks | // Build blocks | ||||
TestMemPoolEntryHelper entry; | TestMemPoolEntryHelper entry; | ||||
entry.nFee = 1337 * SATOSHI; | entry.nFee = 1337 * SATOSHI; | ||||
for (const auto &chain : chains) { | for (const auto &chain : chains) { | ||||
{ | { | ||||
entry.spendsCoinbase = true; | entry.spendsCoinbase = true; | ||||
LOCK2(cs_main, mempool.cs); | LOCK2(cs_main, mempool.cs); | ||||
for (const auto &tx : chain) { | for (const auto &tx : chain) { | ||||
Show All 11 Lines | for (const auto &chain : chains) { | ||||
chain.size() + 1 /* coinbase */); | chain.size() + 1 /* coinbase */); | ||||
if (blockToInvalidate == nullptr) { | if (blockToInvalidate == nullptr) { | ||||
blockToInvalidate = activeChainState.m_chain.Tip(); | blockToInvalidate = activeChainState.m_chain.Tip(); | ||||
} | } | ||||
} | } | ||||
CBlockIndex *mostWorkTip = activeChainState.m_chain.Tip(); | CBlockIndex *mostWorkTip = activeChainState.m_chain.Tip(); | ||||
// `AcceptToMemoryPool` is used during re-org, so we need to ajust its | |||||
// limits. | |||||
gArgs.ForceSetArg("-limitdescendantcount", ToString(chainSizePerBlock)); | |||||
gArgs.ForceSetArg("-limitancestorcount", ToString(chainSizePerBlock)); | |||||
gArgs.ForceSetArg("-limitancestorsize", ToString(chainSizePerBlock * 1000)); | |||||
gArgs.ForceSetArg("-limitdescendantsize", | |||||
ToString(chainSizePerBlock * 1000)); | |||||
bench.run([&] { | bench.run([&] { | ||||
BlockValidationState state; | BlockValidationState state; | ||||
// Disconnect blocks with long transaction chains | // Disconnect blocks with long transaction chains | ||||
activeChainState.InvalidateBlock(config, state, blockToInvalidate); | activeChainState.InvalidateBlock(config, state, blockToInvalidate); | ||||
assert(state.IsValid()); | assert(state.IsValid()); | ||||
activeChainState.ActivateBestChain(config, state); | activeChainState.ActivateBestChain(config, state); | ||||
Show All 16 Lines | bench.run([&] { | ||||
activeChainState.ResetBlockFailureFlags(blockToInvalidate); | activeChainState.ResetBlockFailureFlags(blockToInvalidate); | ||||
} | } | ||||
activeChainState.ActivateBestChain(config, state); | activeChainState.ActivateBestChain(config, state); | ||||
assert(state.IsValid()); | assert(state.IsValid()); | ||||
assert(activeChainState.m_chain.Tip() == mostWorkTip); | assert(activeChainState.m_chain.Tip() == mostWorkTip); | ||||
assert(mempool.size() == 0); | assert(mempool.size() == 0); | ||||
}); | }); | ||||
// restore state | |||||
mempool.wellingtonLatched = wellingtonBefore; | |||||
gArgs.ClearForcedArg("-limitdescendantcount"); | |||||
gArgs.ClearForcedArg("-limitancestorcount"); | |||||
gArgs.ClearForcedArg("-limitancestorsize"); | |||||
gArgs.ClearForcedArg("-limitdescendantsize"); | |||||
} | } | ||||
static void | static void | ||||
benchGenerateNewBlock(const Config &config, node::NodeContext &node, | benchGenerateNewBlock(const Config &config, node::NodeContext &node, | ||||
benchmark::Bench &bench, | benchmark::Bench &bench, | ||||
const std::vector<std::vector<CTransactionRef>> &chains) { | const std::vector<std::vector<CTransactionRef>> &chains) { | ||||
TestMemPoolEntryHelper entry; | TestMemPoolEntryHelper entry; | ||||
entry.nFee = 1337 * SATOSHI; | entry.nFee = 1337 * SATOSHI; | ||||
auto chainman = Assert(node.chainman.get()); | auto chainman = Assert(node.chainman.get()); | ||||
Chainstate &activeChainState = chainman->ActiveChainstate(); | Chainstate &activeChainState = chainman->ActiveChainstate(); | ||||
CTxMemPool &mempool{*Assert(activeChainState.GetMempool())}; | CTxMemPool &mempool{*Assert(activeChainState.GetMempool())}; | ||||
// test with wellington latched (faster) | |||||
const bool wellingtonBefore = mempool.wellingtonLatched.exchange(true); | |||||
// Fill mempool | // Fill mempool | ||||
size_t txCount = 0; | size_t txCount = 0; | ||||
for (const auto &chain : chains) { | for (const auto &chain : chains) { | ||||
entry.spendsCoinbase = true; | entry.spendsCoinbase = true; | ||||
LOCK2(cs_main, mempool.cs); | LOCK2(cs_main, mempool.cs); | ||||
for (const auto &tx : chain) { | for (const auto &tx : chain) { | ||||
mempool.addUnchecked(entry.FromTx(tx)); | mempool.addUnchecked(entry.FromTx(tx)); | ||||
// Setting spendCoinbase to false here assumes it's a chain of | // Setting spendCoinbase to false here assumes it's a chain of | ||||
// 1-in-1-out transaction chain. | // 1-in-1-out transaction chain. | ||||
entry.spendsCoinbase = false; | entry.spendsCoinbase = false; | ||||
++txCount; | ++txCount; | ||||
} | } | ||||
} | } | ||||
assert(mempool.size() == txCount); | assert(mempool.size() == txCount); | ||||
const CScript dummy = CScript() << OP_TRUE; | const CScript dummy = CScript() << OP_TRUE; | ||||
bench.run([&] { | bench.run([&] { | ||||
auto blocktemplate = | auto blocktemplate = | ||||
node::BlockAssembler(config, activeChainState, mempool) | node::BlockAssembler(config, activeChainState, mempool) | ||||
.CreateNewBlock(dummy); | .CreateNewBlock(dummy); | ||||
assert(blocktemplate); | assert(blocktemplate); | ||||
// +1 for coinbase | // +1 for coinbase | ||||
assert(blocktemplate->block.vtx.size() == txCount + 1); | assert(blocktemplate->block.vtx.size() == txCount + 1); | ||||
}); | }); | ||||
// restore state | |||||
mempool.wellingtonLatched = wellingtonBefore; | |||||
} | } | ||||
static void | static void | ||||
benchEviction(const Config &, benchmark::Bench &bench, | benchEviction(const Config &, benchmark::Bench &bench, | ||||
const std::vector<std::vector<CTransactionRef>> &chains, | const std::vector<std::vector<CTransactionRef>> &chains, | ||||
bool revFee = true) { | bool revFee = true) { | ||||
std::list<CTxMemPool> pools; | std::list<CTxMemPool> pools; | ||||
// Note: in order to isolate how long eviction takes (as opposed to add + | // Note: in order to isolate how long eviction takes (as opposed to add + | ||||
// eviction), we are forced to pre-create all the pools we will be needing | // eviction), we are forced to pre-create all the pools we will be needing | ||||
// up front. | // up front. | ||||
bench.epochs(2).epochIterations(1); | bench.epochs(2).epochIterations(1); | ||||
for (uint64_t i = 0; i < bench.epochs() * bench.epochIterations() + 1; | for (uint64_t i = 0; i < bench.epochs() * bench.epochIterations() + 1; | ||||
++i) { | ++i) { | ||||
pools.emplace_back(); | pools.emplace_back(); | ||||
CTxMemPool &pool = pools.back(); | CTxMemPool &pool = pools.back(); | ||||
// test with wellington latched (faster) | |||||
pool.wellingtonLatched = true; | |||||
TestMemPoolEntryHelper entry; | TestMemPoolEntryHelper entry; | ||||
// Fill mempool | // Fill mempool | ||||
size_t txCount = 0; | size_t txCount = 0; | ||||
entry.nFee = 1337 * SATOSHI; | entry.nFee = 1337 * SATOSHI; | ||||
// add in order of decreasing fee if revFee, increasing otherwise | // add in order of decreasing fee if revFee, increasing otherwise | ||||
const Amount feeBump = | const Amount feeBump = | ||||
revFee ? int64_t(-1) * SATOSHI : int64_t(1) * SATOSHI; | revFee ? int64_t(-1) * SATOSHI : int64_t(1) * SATOSHI; | ||||
for (const auto &chain : chains) { | for (const auto &chain : chains) { | ||||
▲ Show 20 Lines • Show All 168 Lines • Show Last 20 Lines |