Skip to content

Commit 5e78fbf

Browse files
committed
wallet: setup wallet threadpool
All wallets will use the same ThreadPool owned by the WalletContext. ThreadPool::Submit() is threadsafe so there's no need for the use of external synchronization primitives when submiting tasks. All threads started by the ThreadPool will be destroyed with the ThreadPool and WalletContext.
1 parent 1590b2f commit 5e78fbf

File tree

8 files changed

+31
-5
lines changed

8 files changed

+31
-5
lines changed

src/dummywallet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ void DummyWalletInit::AddWalletOptions(ArgsManager& argsman) const
4747
"-walletdir=<dir>",
4848
"-walletnotify=<cmd>",
4949
"-walletrbf",
50+
"-walletpar",
5051
"-walletrejectlongchains",
5152
"-walletcrosschain",
5253
"-unsafesqlitesync",

src/wallet/context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define BITCOIN_WALLET_CONTEXT_H
77

88
#include <sync.h>
9+
#include <util/threadpool.h>
910

1011
#include <functional>
1112
#include <list>
@@ -39,6 +40,7 @@ struct WalletContext {
3940
ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
4041
// It is unsafe to lock this after locking a CWallet::cs_wallet mutex because
4142
// this could introduce inconsistent lock ordering and cause deadlocks.
43+
ThreadPool thread_pool{"wallet"}; //!< Thread pool for wallet operations
4244
Mutex wallets_mutex;
4345
std::vector<std::shared_ptr<CWallet>> wallets GUARDED_BY(wallets_mutex);
4446
std::list<LoadWalletFn> wallet_load_fns GUARDED_BY(wallets_mutex);

src/wallet/dump.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <common/args.h>
88
#include <util/fs.h>
9+
#include <util/threadpool.h>
910
#include <util/translation.h>
1011
#include <wallet/wallet.h>
1112
#include <wallet/walletdb.h>

src/wallet/init.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const
7777
argsman.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes. %s in cmd is replaced by TxID, %w is replaced by wallet name, %b is replaced by the hash of the block including the transaction (set to 'unconfirmed' if the transaction is not included) and %h is replaced by the block height (-1 if not included). %w is not currently implemented on windows. On systems where %w is supported, it should NOT be quoted because this would break shell escaping used to invoke the command.", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
7878
#endif
7979
argsman.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
80+
argsman.AddArg("-walletpar=<n>", strprintf("Number of threads to use for wallet operations (0 = auto, up to %d, <0 = leave that many cores free, default: %d)", MAX_WALLETPAR, DEFAULT_WALLETPAR), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
8081

8182
argsman.AddArg("-unsafesqlitesync", "Set SQLite synchronous=OFF to disable waiting for the database to sync to disk. This is unsafe and can cause data loss and corruption. This option is only used by tests to improve their performance (default: false)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
8283

src/wallet/interfaces.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <interfaces/wallet.h>
66

77
#include <common/args.h>
8+
#include <common/system.h>
89
#include <consensus/amount.h>
910
#include <interfaces/chain.h>
1011
#include <interfaces/handler.h>
@@ -29,6 +30,7 @@
2930
#include <wallet/spend.h>
3031
#include <wallet/wallet.h>
3132

33+
#include <algorithm>
3234
#include <memory>
3335
#include <string>
3436
#include <utility>
@@ -544,6 +546,14 @@ class WalletLoaderImpl : public WalletLoader
544546
{
545547
m_context.chain = &chain;
546548
m_context.args = &args;
549+
int num_threads = args.GetIntArg("-walletpar", DEFAULT_WALLETPAR);
550+
if (num_threads <= 0) {
551+
// '0' means 'autodetect'
552+
// '<0' means leave that many cores free
553+
num_threads += GetNumCores();
554+
}
555+
num_threads = std::clamp(num_threads, 1, MAX_WALLETPAR);
556+
m_context.thread_pool.Start(num_threads);
547557
}
548558
~WalletLoaderImpl() override { stop(); }
549559

src/wallet/test/util.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <key_io.h>
1010
#include <streams.h>
1111
#include <test/util/setup_common.h>
12+
#include <util/threadpool.h>
1213
#include <validationinterface.h>
1314
#include <wallet/context.h>
1415
#include <wallet/wallet.h>
@@ -19,7 +20,9 @@
1920
namespace wallet {
2021
std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key)
2122
{
22-
auto wallet = std::make_unique<CWallet>(&chain, "", CreateMockableWalletDatabase());
23+
ThreadPool thread_pool{"wallet_test"};
24+
thread_pool.Start(2);
25+
auto wallet = std::make_unique<CWallet>(&chain, "", CreateMockableWalletDatabase(), &thread_pool);
2326
{
2427
LOCK2(wallet->cs_wallet, ::cs_main);
2528
wallet->SetLastBlockProcessed(cchain.Height(), cchain.Tip()->GetBlockHash());

src/wallet/wallet.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3206,7 +3206,7 @@ std::shared_ptr<CWallet> CWallet::CreateNew(WalletContext& context, const std::s
32063206
const auto start{SteadyClock::now()};
32073207
// TODO: Can't use std::make_shared because we need a custom deleter but
32083208
// should be possible to use std::allocate_shared.
3209-
std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), FlushAndDeleteWallet);
3209+
std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database), &context.thread_pool), FlushAndDeleteWallet);
32103210

32113211
if (!LoadWalletArgs(walletInstance, context, error, warnings)) {
32123212
return nullptr;
@@ -3258,7 +3258,7 @@ std::shared_ptr<CWallet> CWallet::LoadExisting(WalletContext& context, const std
32583258
const std::string& walletFile = database->Filename();
32593259

32603260
const auto start{SteadyClock::now()};
3261-
std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), FlushAndDeleteWallet);
3261+
std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database), &context.thread_pool), FlushAndDeleteWallet);
32623262

32633263
if (!LoadWalletArgs(walletInstance, context, error, warnings)) {
32643264
return nullptr;

src/wallet/wallet.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <util/hasher.h>
2828
#include <util/result.h>
2929
#include <util/string.h>
30+
#include <util/threadpool.h>
3031
#include <util/time.h>
3132
#include <util/ui_change_type.h>
3233
#include <wallet/crypter.h>
@@ -135,6 +136,9 @@ static const bool DEFAULT_WALLET_RBF = true;
135136
static const bool DEFAULT_WALLETBROADCAST = true;
136137
static const bool DEFAULT_DISABLE_WALLET = false;
137138
static const bool DEFAULT_WALLETCROSSCHAIN = false;
139+
//! Default for -walletpar
140+
static const int DEFAULT_WALLETPAR = 0;
141+
static const int MAX_WALLETPAR = 16;
138142
//! -maxtxfee default
139143
constexpr CAmount DEFAULT_TRANSACTION_MAXFEE{COIN / 10};
140144
//! Discourage users to set fees higher than this amount (in satoshis) per kB
@@ -403,6 +407,9 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
403407
/** Internal database handle. */
404408
std::unique_ptr<WalletDatabase> m_database;
405409

410+
/** Thread pool for wallet operations. */
411+
[[maybe_unused]] ThreadPool* m_thread_pool;
412+
406413
/**
407414
* The following is used to keep track of how far behind the wallet is
408415
* from the chain sync, and to allow clients to block on us being caught up.
@@ -479,10 +486,11 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
479486
unsigned int nMasterKeyMaxID = 0;
480487

481488
/** Construct wallet with specified name and database implementation. */
482-
CWallet(interfaces::Chain* chain, const std::string& name, std::unique_ptr<WalletDatabase> database)
489+
CWallet(interfaces::Chain* chain, const std::string& name, std::unique_ptr<WalletDatabase> database, ThreadPool* thread_pool = nullptr)
483490
: m_chain(chain),
484491
m_name(name),
485-
m_database(std::move(database))
492+
m_database(std::move(database)),
493+
m_thread_pool(thread_pool)
486494
{
487495
}
488496

0 commit comments

Comments
 (0)