mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-27 01:11:59 +02:00
Add local thread pool to CCheckQueue
This commit is contained in:
parent
0ef938685b
commit
01511776ac
@ -6,6 +6,8 @@
|
|||||||
#define BITCOIN_CHECKQUEUE_H
|
#define BITCOIN_CHECKQUEUE_H
|
||||||
|
|
||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
|
#include <tinyformat.h>
|
||||||
|
#include <util/threadnames.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -62,8 +64,11 @@ private:
|
|||||||
//! The maximum number of elements to be processed in one batch
|
//! The maximum number of elements to be processed in one batch
|
||||||
const unsigned int nBatchSize;
|
const unsigned int nBatchSize;
|
||||||
|
|
||||||
|
std::vector<std::thread> m_worker_threads;
|
||||||
|
bool m_request_stop{false};
|
||||||
|
|
||||||
/** Internal function that does bulk of the verification work. */
|
/** Internal function that does bulk of the verification work. */
|
||||||
bool Loop(bool fMaster = false)
|
bool Loop(bool fMaster)
|
||||||
{
|
{
|
||||||
boost::condition_variable& cond = fMaster ? condMaster : condWorker;
|
boost::condition_variable& cond = fMaster ? condMaster : condWorker;
|
||||||
std::vector<T> vChecks;
|
std::vector<T> vChecks;
|
||||||
@ -85,7 +90,7 @@ private:
|
|||||||
nTotal++;
|
nTotal++;
|
||||||
}
|
}
|
||||||
// logically, the do loop starts here
|
// logically, the do loop starts here
|
||||||
while (queue.empty()) {
|
while (queue.empty() && !m_request_stop) {
|
||||||
if (fMaster && nTodo == 0) {
|
if (fMaster && nTodo == 0) {
|
||||||
nTotal--;
|
nTotal--;
|
||||||
bool fRet = fAllOk;
|
bool fRet = fAllOk;
|
||||||
@ -98,6 +103,10 @@ private:
|
|||||||
cond.wait(lock); // wait
|
cond.wait(lock); // wait
|
||||||
nIdle--;
|
nIdle--;
|
||||||
}
|
}
|
||||||
|
if (m_request_stop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Decide how many work units to process now.
|
// Decide how many work units to process now.
|
||||||
// * Do not try to do everything at once, but aim for increasingly smaller batches so
|
// * Do not try to do everything at once, but aim for increasingly smaller batches so
|
||||||
// all workers finish approximately simultaneously.
|
// all workers finish approximately simultaneously.
|
||||||
@ -132,16 +141,34 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Create a pool of new worker threads.
|
||||||
|
void StartWorkerThreads(const int threads_num)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::mutex> lock(mutex);
|
||||||
|
nIdle = 0;
|
||||||
|
nTotal = 0;
|
||||||
|
fAllOk = true;
|
||||||
|
}
|
||||||
|
assert(m_worker_threads.empty());
|
||||||
|
for (int n = 0; n < threads_num; ++n) {
|
||||||
|
m_worker_threads.emplace_back([this, n]() {
|
||||||
|
util::ThreadRename(strprintf("scriptch.%i", n));
|
||||||
|
Loop(false /* worker thread */);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//! Worker thread
|
//! Worker thread
|
||||||
void Thread()
|
void Thread()
|
||||||
{
|
{
|
||||||
Loop();
|
Loop(false /* worker thread */);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Wait until execution finishes, and return whether all evaluations were successful.
|
//! Wait until execution finishes, and return whether all evaluations were successful.
|
||||||
bool Wait()
|
bool Wait()
|
||||||
{
|
{
|
||||||
return Loop(true);
|
return Loop(true /* master thread */);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Add a batch of checks to the queue
|
//! Add a batch of checks to the queue
|
||||||
@ -159,8 +186,25 @@ public:
|
|||||||
condWorker.notify_all();
|
condWorker.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Stop all of the worker threads.
|
||||||
|
void StopWorkerThreads()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::mutex> lock(mutex);
|
||||||
|
m_request_stop = true;
|
||||||
|
}
|
||||||
|
condWorker.notify_all();
|
||||||
|
for (std::thread& t : m_worker_threads) {
|
||||||
|
t.join();
|
||||||
|
}
|
||||||
|
m_worker_threads.clear();
|
||||||
|
boost::unique_lock<boost::mutex> lock(mutex);
|
||||||
|
m_request_stop = false;
|
||||||
|
}
|
||||||
|
|
||||||
~CCheckQueue()
|
~CCheckQueue()
|
||||||
{
|
{
|
||||||
|
assert(m_worker_threads.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -224,6 +224,7 @@ void Shutdown(NodeContext& node)
|
|||||||
if (g_load_block.joinable()) g_load_block.join();
|
if (g_load_block.joinable()) g_load_block.join();
|
||||||
threadGroup.interrupt_all();
|
threadGroup.interrupt_all();
|
||||||
threadGroup.join_all();
|
threadGroup.join_all();
|
||||||
|
StopScriptCheckWorkerThreads();
|
||||||
|
|
||||||
// After the threads that potentially access these pointers have been stopped,
|
// After the threads that potentially access these pointers have been stopped,
|
||||||
// destruct and reset all to nullptr.
|
// destruct and reset all to nullptr.
|
||||||
@ -1307,9 +1308,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
|
|||||||
LogPrintf("Script verification uses %d additional threads\n", script_threads);
|
LogPrintf("Script verification uses %d additional threads\n", script_threads);
|
||||||
if (script_threads >= 1) {
|
if (script_threads >= 1) {
|
||||||
g_parallel_script_checks = true;
|
g_parallel_script_checks = true;
|
||||||
for (int i = 0; i < script_threads; ++i) {
|
StartScriptCheckWorkerThreads(script_threads);
|
||||||
threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!node.scheduler);
|
assert(!node.scheduler);
|
||||||
|
@ -162,9 +162,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
|
|||||||
|
|
||||||
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
|
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
|
||||||
constexpr int script_check_threads = 2;
|
constexpr int script_check_threads = 2;
|
||||||
for (int i = 0; i < script_check_threads; ++i) {
|
StartScriptCheckWorkerThreads(script_check_threads);
|
||||||
threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
|
|
||||||
}
|
|
||||||
g_parallel_script_checks = true;
|
g_parallel_script_checks = true;
|
||||||
|
|
||||||
m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
||||||
@ -182,6 +180,7 @@ TestingSetup::~TestingSetup()
|
|||||||
if (m_node.scheduler) m_node.scheduler->stop();
|
if (m_node.scheduler) m_node.scheduler->stop();
|
||||||
threadGroup.interrupt_all();
|
threadGroup.interrupt_all();
|
||||||
threadGroup.join_all();
|
threadGroup.join_all();
|
||||||
|
StopScriptCheckWorkerThreads();
|
||||||
GetMainSignals().FlushBackgroundCallbacks();
|
GetMainSignals().FlushBackgroundCallbacks();
|
||||||
GetMainSignals().UnregisterBackgroundSignalScheduler();
|
GetMainSignals().UnregisterBackgroundSignalScheduler();
|
||||||
m_node.connman.reset();
|
m_node.connman.reset();
|
||||||
|
@ -1817,9 +1817,14 @@ static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationSt
|
|||||||
|
|
||||||
static CCheckQueue<CScriptCheck> scriptcheckqueue(128);
|
static CCheckQueue<CScriptCheck> scriptcheckqueue(128);
|
||||||
|
|
||||||
void ThreadScriptCheck(int worker_num) {
|
void StartScriptCheckWorkerThreads(int threads_num)
|
||||||
util::ThreadRename(strprintf("scriptch.%i", worker_num));
|
{
|
||||||
scriptcheckqueue.Thread();
|
scriptcheckqueue.StartWorkerThreads(threads_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopScriptCheckWorkerThreads()
|
||||||
|
{
|
||||||
|
scriptcheckqueue.StopWorkerThreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionBitsCache versionbitscache GUARDED_BY(cs_main);
|
VersionBitsCache versionbitscache GUARDED_BY(cs_main);
|
||||||
|
@ -158,8 +158,10 @@ void LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFi
|
|||||||
bool LoadGenesisBlock(const CChainParams& chainparams);
|
bool LoadGenesisBlock(const CChainParams& chainparams);
|
||||||
/** Unload database information */
|
/** Unload database information */
|
||||||
void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman);
|
void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman);
|
||||||
/** Run an instance of the script checking thread */
|
/** Run instances of script checking worker threads */
|
||||||
void ThreadScriptCheck(int worker_num);
|
void StartScriptCheckWorkerThreads(int threads_num);
|
||||||
|
/** Stop all of the script checking worker threads */
|
||||||
|
void StopScriptCheckWorkerThreads();
|
||||||
/**
|
/**
|
||||||
* Return transaction from the block at block_index.
|
* Return transaction from the block at block_index.
|
||||||
* If block_index is not provided, fall back to mempool.
|
* If block_index is not provided, fall back to mempool.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user