Merge #8873: Add microbenchmarks to profile more code paths.
18dacf9 Add microbenchmarks to profile more code paths. (Russell Yanofsky)
This commit is contained in:
parent
6e871c0c2e
commit
2f8677391a
@ -14,6 +14,8 @@ bench_bench_dash_SOURCES = \
|
||||
bench/Examples.cpp \
|
||||
bench/rollingbloom.cpp \
|
||||
bench/crypto_hash.cpp \
|
||||
bench/ccoins_caching.cpp \
|
||||
bench/mempool_eviction.cpp \
|
||||
bench/base58.cpp
|
||||
|
||||
bench_bench_dash_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
|
||||
@ -34,7 +36,8 @@ bench_bench_dash_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
|
||||
endif
|
||||
|
||||
if ENABLE_WALLET
|
||||
bench_bench_dash_LDADD += $(LIBBITCOIN_WALLET)
|
||||
bench_bench_dash_SOURCES += bench/coin_selection.cpp
|
||||
bench_bench_dash_LDADD += $(LIBBITCOIN_WALLET) $(LIBBITCOIN_CRYPTO)
|
||||
endif
|
||||
|
||||
bench_bench_dash_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
|
||||
|
87
src/bench/ccoins_caching.cpp
Normal file
87
src/bench/ccoins_caching.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2016 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 "bench.h"
|
||||
#include "coins.h"
|
||||
#include "policy/policy.h"
|
||||
#include "wallet/crypter.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// FIXME: Dedup with SetupDummyInputs in test/transaction_tests.cpp.
|
||||
//
|
||||
// Helper: create two dummy transactions, each with
|
||||
// two outputs. The first has 11 and 50 CENT outputs
|
||||
// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
|
||||
// paid to a TX_PUBKEYHASH.
|
||||
//
|
||||
static std::vector<CMutableTransaction>
|
||||
SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsViewCache& coinsRet)
|
||||
{
|
||||
std::vector<CMutableTransaction> dummyTransactions;
|
||||
dummyTransactions.resize(2);
|
||||
|
||||
// Add some keys to the keystore:
|
||||
CKey key[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
key[i].MakeNewKey(i % 2);
|
||||
keystoreRet.AddKey(key[i]);
|
||||
}
|
||||
|
||||
// Create some dummy input transactions
|
||||
dummyTransactions[0].vout.resize(2);
|
||||
dummyTransactions[0].vout[0].nValue = 11 * CENT;
|
||||
dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
|
||||
dummyTransactions[0].vout[1].nValue = 50 * CENT;
|
||||
dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
|
||||
coinsRet.ModifyCoins(dummyTransactions[0].GetHash())->FromTx(dummyTransactions[0], 0);
|
||||
|
||||
dummyTransactions[1].vout.resize(2);
|
||||
dummyTransactions[1].vout[0].nValue = 21 * CENT;
|
||||
dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(key[2].GetPubKey().GetID());
|
||||
dummyTransactions[1].vout[1].nValue = 22 * CENT;
|
||||
dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID());
|
||||
coinsRet.ModifyCoins(dummyTransactions[1].GetHash())->FromTx(dummyTransactions[1], 0);
|
||||
|
||||
return dummyTransactions;
|
||||
}
|
||||
|
||||
// Microbenchmark for simple accesses to a CCoinsViewCache database. Note from
|
||||
// laanwj, "replicating the actual usage patterns of the client is hard though,
|
||||
// many times micro-benchmarks of the database showed completely different
|
||||
// characteristics than e.g. reindex timings. But that's not a requirement of
|
||||
// every benchmark."
|
||||
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
|
||||
static void CCoinsCaching(benchmark::State& state)
|
||||
{
|
||||
CBasicKeyStore keystore;
|
||||
CCoinsView coinsDummy;
|
||||
CCoinsViewCache coins(&coinsDummy);
|
||||
std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
|
||||
|
||||
CMutableTransaction t1;
|
||||
t1.vin.resize(3);
|
||||
t1.vin[0].prevout.hash = dummyTransactions[0].GetHash();
|
||||
t1.vin[0].prevout.n = 1;
|
||||
t1.vin[0].scriptSig << std::vector<unsigned char>(65, 0);
|
||||
t1.vin[1].prevout.hash = dummyTransactions[1].GetHash();
|
||||
t1.vin[1].prevout.n = 0;
|
||||
t1.vin[1].scriptSig << std::vector<unsigned char>(65, 0) << std::vector<unsigned char>(33, 4);
|
||||
t1.vin[2].prevout.hash = dummyTransactions[1].GetHash();
|
||||
t1.vin[2].prevout.n = 1;
|
||||
t1.vin[2].scriptSig << std::vector<unsigned char>(65, 0) << std::vector<unsigned char>(33, 4);
|
||||
t1.vout.resize(2);
|
||||
t1.vout[0].nValue = 90 * CENT;
|
||||
t1.vout[0].scriptPubKey << OP_1;
|
||||
|
||||
// Benchmark.
|
||||
while (state.KeepRunning()) {
|
||||
bool success = AreInputsStandard(t1, coins);
|
||||
assert(success);
|
||||
CAmount value = coins.GetValueIn(t1);
|
||||
assert(value == (50 + 21 + 22) * CENT);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(CCoinsCaching);
|
62
src/bench/coin_selection.cpp
Normal file
62
src/bench/coin_selection.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2012-2015 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 "bench.h"
|
||||
#include "wallet/wallet.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <set>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static void addCoin(const CAmount& nValue, const CWallet& wallet, vector<COutput>& vCoins)
|
||||
{
|
||||
int nInput = 0;
|
||||
|
||||
static int nextLockTime = 0;
|
||||
CMutableTransaction tx;
|
||||
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
|
||||
tx.vout.resize(nInput + 1);
|
||||
tx.vout[nInput].nValue = nValue;
|
||||
CWalletTx* wtx = new CWalletTx(&wallet, tx);
|
||||
|
||||
int nAge = 6 * 24;
|
||||
COutput output(wtx, nInput, nAge, true, true);
|
||||
vCoins.push_back(output);
|
||||
}
|
||||
|
||||
// Simple benchmark for wallet coin selection. Note that it maybe be necessary
|
||||
// to build up more complicated scenarios in order to get meaningful
|
||||
// measurements of performance. From laanwj, "Wallet coin selection is probably
|
||||
// the hardest, as you need a wider selection of scenarios, just testing the
|
||||
// same one over and over isn't too useful. Generating random isn't useful
|
||||
// either for measurements."
|
||||
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
|
||||
static void CoinSelection(benchmark::State& state)
|
||||
{
|
||||
const CWallet wallet;
|
||||
vector<COutput> vCoins;
|
||||
LOCK(wallet.cs_wallet);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
// Empty wallet.
|
||||
BOOST_FOREACH (COutput output, vCoins)
|
||||
delete output.tx;
|
||||
vCoins.clear();
|
||||
|
||||
// Add coins.
|
||||
for (int i = 0; i < 1000; i++)
|
||||
addCoin(1000 * COIN, wallet, vCoins);
|
||||
addCoin(3 * COIN, wallet, vCoins);
|
||||
|
||||
set<pair<const CWalletTx*, unsigned int> > setCoinsRet;
|
||||
CAmount nValueRet;
|
||||
bool success = wallet.SelectCoinsMinConf(1003 * COIN, 1, 6, vCoins, setCoinsRet, nValueRet);
|
||||
assert(success);
|
||||
assert(nValueRet == 1003 * COIN);
|
||||
assert(setCoinsRet.size() == 2);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(CoinSelection);
|
115
src/bench/mempool_eviction.cpp
Normal file
115
src/bench/mempool_eviction.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright (c) 2011-2015 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 "bench.h"
|
||||
#include "policy/policy.h"
|
||||
#include "txmempool.h"
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
static void AddTx(const CTransaction& tx, const CAmount& nFee, CTxMemPool& pool)
|
||||
{
|
||||
int64_t nTime = 0;
|
||||
double dPriority = 10.0;
|
||||
unsigned int nHeight = 1;
|
||||
bool spendsCoinbase = false;
|
||||
unsigned int sigOpCost = 4;
|
||||
LockPoints lp;
|
||||
pool.addUnchecked(tx.GetHash(), CTxMemPoolEntry(
|
||||
tx, nFee, nTime, dPriority, nHeight, pool.HasNoInputsOf(tx),
|
||||
tx.GetValueOut(), spendsCoinbase, sigOpCost, lp));
|
||||
}
|
||||
|
||||
// Right now this is only testing eviction performance in an extremely small
|
||||
// mempool. Code needs to be written to generate a much wider variety of
|
||||
// unique transactions for a more meaningful performance measurement.
|
||||
static void MempoolEviction(benchmark::State& state)
|
||||
{
|
||||
CMutableTransaction tx1 = CMutableTransaction();
|
||||
tx1.vin.resize(1);
|
||||
tx1.vin[0].scriptSig = CScript() << OP_1;
|
||||
tx1.vout.resize(1);
|
||||
tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
|
||||
tx1.vout[0].nValue = 10 * COIN;
|
||||
|
||||
CMutableTransaction tx2 = CMutableTransaction();
|
||||
tx2.vin.resize(1);
|
||||
tx2.vin[0].scriptSig = CScript() << OP_2;
|
||||
tx2.vout.resize(1);
|
||||
tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
|
||||
tx2.vout[0].nValue = 10 * COIN;
|
||||
|
||||
CMutableTransaction tx3 = CMutableTransaction();
|
||||
tx3.vin.resize(1);
|
||||
tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0);
|
||||
tx3.vin[0].scriptSig = CScript() << OP_2;
|
||||
tx3.vout.resize(1);
|
||||
tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
|
||||
tx3.vout[0].nValue = 10 * COIN;
|
||||
|
||||
CMutableTransaction tx4 = CMutableTransaction();
|
||||
tx4.vin.resize(2);
|
||||
tx4.vin[0].prevout.SetNull();
|
||||
tx4.vin[0].scriptSig = CScript() << OP_4;
|
||||
tx4.vin[1].prevout.SetNull();
|
||||
tx4.vin[1].scriptSig = CScript() << OP_4;
|
||||
tx4.vout.resize(2);
|
||||
tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
|
||||
tx4.vout[0].nValue = 10 * COIN;
|
||||
tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
|
||||
tx4.vout[1].nValue = 10 * COIN;
|
||||
|
||||
CMutableTransaction tx5 = CMutableTransaction();
|
||||
tx5.vin.resize(2);
|
||||
tx5.vin[0].prevout = COutPoint(tx4.GetHash(), 0);
|
||||
tx5.vin[0].scriptSig = CScript() << OP_4;
|
||||
tx5.vin[1].prevout.SetNull();
|
||||
tx5.vin[1].scriptSig = CScript() << OP_5;
|
||||
tx5.vout.resize(2);
|
||||
tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
|
||||
tx5.vout[0].nValue = 10 * COIN;
|
||||
tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
|
||||
tx5.vout[1].nValue = 10 * COIN;
|
||||
|
||||
CMutableTransaction tx6 = CMutableTransaction();
|
||||
tx6.vin.resize(2);
|
||||
tx6.vin[0].prevout = COutPoint(tx4.GetHash(), 1);
|
||||
tx6.vin[0].scriptSig = CScript() << OP_4;
|
||||
tx6.vin[1].prevout.SetNull();
|
||||
tx6.vin[1].scriptSig = CScript() << OP_6;
|
||||
tx6.vout.resize(2);
|
||||
tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
|
||||
tx6.vout[0].nValue = 10 * COIN;
|
||||
tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
|
||||
tx6.vout[1].nValue = 10 * COIN;
|
||||
|
||||
CMutableTransaction tx7 = CMutableTransaction();
|
||||
tx7.vin.resize(2);
|
||||
tx7.vin[0].prevout = COutPoint(tx5.GetHash(), 0);
|
||||
tx7.vin[0].scriptSig = CScript() << OP_5;
|
||||
tx7.vin[1].prevout = COutPoint(tx6.GetHash(), 0);
|
||||
tx7.vin[1].scriptSig = CScript() << OP_6;
|
||||
tx7.vout.resize(2);
|
||||
tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
|
||||
tx7.vout[0].nValue = 10 * COIN;
|
||||
tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
|
||||
tx7.vout[1].nValue = 10 * COIN;
|
||||
|
||||
CTxMemPool pool(CFeeRate(1000));
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
AddTx(tx1, 10000LL, pool);
|
||||
AddTx(tx2, 5000LL, pool);
|
||||
AddTx(tx3, 20000LL, pool);
|
||||
AddTx(tx4, 7000LL, pool);
|
||||
AddTx(tx5, 1000LL, pool);
|
||||
AddTx(tx6, 1100LL, pool);
|
||||
AddTx(tx7, 9000LL, pool);
|
||||
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4);
|
||||
pool.TrimToSize(::GetSerializeSize(tx1, SER_NETWORK, PROTOCOL_VERSION));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(MempoolEviction);
|
Loading…
Reference in New Issue
Block a user