Changeset View
Changeset View
Standalone View
Standalone View
src/bench/coin_selection.cpp
Show All 25 Lines | |||||
// Simple benchmark for wallet coin selection. Note that it maybe be necessary | // Simple benchmark for wallet coin selection. Note that it maybe be necessary | ||||
// to build up more complicated scenarios in order to get meaningful | // to build up more complicated scenarios in order to get meaningful | ||||
// measurements of performance. From laanwj, "Wallet coin selection is probably | // measurements of performance. From laanwj, "Wallet coin selection is probably | ||||
// the hardest, as you need a wider selection of scenarios, just testing the | // 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 | // same one over and over isn't too useful. Generating random isn't useful | ||||
// either for measurements." | // either for measurements." | ||||
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484) | // (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484) | ||||
static void CoinSelection(benchmark::State &state) { | static void CoinSelection(benchmark::Bench &bench) { | ||||
SelectParams(CBaseChainParams::REGTEST); | SelectParams(CBaseChainParams::REGTEST); | ||||
NodeContext node; | NodeContext node; | ||||
auto chain = interfaces::MakeChain(node, Params()); | auto chain = interfaces::MakeChain(node, Params()); | ||||
CWallet wallet(chain.get(), WalletLocation(), | CWallet wallet(chain.get(), WalletLocation(), | ||||
WalletDatabase::CreateDummy()); | WalletDatabase::CreateDummy()); | ||||
wallet.SetupLegacyScriptPubKeyMan(); | wallet.SetupLegacyScriptPubKeyMan(); | ||||
std::vector<std::unique_ptr<CWalletTx>> wtxs; | std::vector<std::unique_ptr<CWalletTx>> wtxs; | ||||
Show All 12 Lines | for (const auto &wtx : wtxs) { | ||||
true /* spendable */, true /* solvable */, | true /* spendable */, true /* solvable */, | ||||
true /* safe */); | true /* safe */); | ||||
groups.emplace_back(output.GetInputCoin(), 6, false, 0, 0); | groups.emplace_back(output.GetInputCoin(), 6, false, 0, 0); | ||||
} | } | ||||
const CoinEligibilityFilter filter_standard(1, 6, 0); | const CoinEligibilityFilter filter_standard(1, 6, 0); | ||||
const CoinSelectionParams coin_selection_params( | const CoinSelectionParams coin_selection_params( | ||||
true, 34, 148, CFeeRate(Amount::zero()), 0); | true, 34, 148, CFeeRate(Amount::zero()), 0); | ||||
while (state.KeepRunning()) { | bench.run([&] { | ||||
std::set<CInputCoin> setCoinsRet; | std::set<CInputCoin> setCoinsRet; | ||||
Amount nValueRet; | Amount nValueRet; | ||||
bool bnb_used; | bool bnb_used; | ||||
bool success = wallet.SelectCoinsMinConf( | bool success = wallet.SelectCoinsMinConf( | ||||
1003 * COIN, filter_standard, groups, setCoinsRet, nValueRet, | 1003 * COIN, filter_standard, groups, setCoinsRet, nValueRet, | ||||
coin_selection_params, bnb_used); | coin_selection_params, bnb_used); | ||||
assert(success); | assert(success); | ||||
assert(nValueRet == 1003 * COIN); | assert(nValueRet == 1003 * COIN); | ||||
assert(setCoinsRet.size() == 2); | assert(setCoinsRet.size() == 2); | ||||
} | }); | ||||
} | } | ||||
typedef std::set<CInputCoin> CoinSet; | typedef std::set<CInputCoin> CoinSet; | ||||
std::vector<std::unique_ptr<CWalletTx>> wtxn; | std::vector<std::unique_ptr<CWalletTx>> wtxn; | ||||
// Copied from src/wallet/test/coinselector_tests.cpp | // Copied from src/wallet/test/coinselector_tests.cpp | ||||
static void add_coin(const CWallet &wallet, const Amount nValue, int nInput, | static void add_coin(const CWallet &wallet, const Amount nValue, int nInput, | ||||
std::vector<OutputGroup> &set) { | std::vector<OutputGroup> &set) { | ||||
Show All 18 Lines | for (int i = 0; i < utxos; ++i) { | ||||
target += base; | target += base; | ||||
add_coin(wallet, base, 2 * i, utxo_pool); | add_coin(wallet, base, 2 * i, utxo_pool); | ||||
add_coin(wallet, base + (int64_t(1) << (utxos - 1 - i)) * SATOSHI, | add_coin(wallet, base + (int64_t(1) << (utxos - 1 - i)) * SATOSHI, | ||||
2 * i + 1, utxo_pool); | 2 * i + 1, utxo_pool); | ||||
} | } | ||||
return target; | return target; | ||||
} | } | ||||
static void BnBExhaustion(benchmark::State &state) { | static void BnBExhaustion(benchmark::Bench &bench) { | ||||
SelectParams(CBaseChainParams::REGTEST); | SelectParams(CBaseChainParams::REGTEST); | ||||
NodeContext node; | NodeContext node; | ||||
auto chain = interfaces::MakeChain(node, Params()); | auto chain = interfaces::MakeChain(node, Params()); | ||||
CWallet wallet(chain.get(), WalletLocation(), | CWallet wallet(chain.get(), WalletLocation(), | ||||
WalletDatabase::CreateDummy()); | WalletDatabase::CreateDummy()); | ||||
LOCK(wallet.cs_wallet); | LOCK(wallet.cs_wallet); | ||||
// Setup | // Setup | ||||
wallet.SetupLegacyScriptPubKeyMan(); | wallet.SetupLegacyScriptPubKeyMan(); | ||||
std::vector<OutputGroup> utxo_pool; | std::vector<OutputGroup> utxo_pool; | ||||
CoinSet selection; | CoinSet selection; | ||||
Amount value_ret = Amount::zero(); | Amount value_ret = Amount::zero(); | ||||
Amount not_input_fees = Amount::zero(); | Amount not_input_fees = Amount::zero(); | ||||
while (state.KeepRunning()) { | bench.run([&] { | ||||
// Benchmark | // Benchmark | ||||
Amount target = make_hard_case(wallet, 17, utxo_pool); | Amount target = make_hard_case(wallet, 17, utxo_pool); | ||||
// Should exhaust | // Should exhaust | ||||
SelectCoinsBnB(utxo_pool, target, Amount::zero(), selection, value_ret, | SelectCoinsBnB(utxo_pool, target, Amount::zero(), selection, value_ret, | ||||
not_input_fees); | not_input_fees); | ||||
// Cleanup | // Cleanup | ||||
utxo_pool.clear(); | utxo_pool.clear(); | ||||
selection.clear(); | selection.clear(); | ||||
} | }); | ||||
} | } | ||||
BENCHMARK(CoinSelection, 650); | BENCHMARK(CoinSelection); | ||||
BENCHMARK(BnBExhaustion, 650); | BENCHMARK(BnBExhaustion); |