Skip to content

Commit 8da0e1f

Browse files
committed
merge bitcoin#17342: Clean up nScriptCheckThreads
17342
1 parent fece1d4 commit 8da0e1f

File tree

5 files changed

+40
-29
lines changed

5 files changed

+40
-29
lines changed

src/init.cpp

+18-12
Original file line numberDiff line numberDiff line change
@@ -1326,15 +1326,6 @@ bool AppInitParameterInteraction()
13261326
incrementalRelayFee = CFeeRate(n);
13271327
}
13281328

1329-
// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
1330-
nScriptCheckThreads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
1331-
if (nScriptCheckThreads <= 0)
1332-
nScriptCheckThreads += GetNumCores();
1333-
if (nScriptCheckThreads <= 1)
1334-
nScriptCheckThreads = 0;
1335-
else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS)
1336-
nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;
1337-
13381329
// block pruning; get the amount of disk space (in MiB) to allot for block & undo files
13391330
int64_t nPruneArg = gArgs.GetArg("-prune", 0);
13401331
if (nPruneArg < 0) {
@@ -1730,10 +1721,25 @@ bool AppInitMain()
17301721
InitSignatureCache();
17311722
InitScriptExecutionCache();
17321723

1733-
LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
1734-
if (nScriptCheckThreads) {
1735-
for (int i=0; i<nScriptCheckThreads-1; i++)
1724+
int script_threads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
1725+
if (script_threads <= 0) {
1726+
// -par=0 means autodetect (number of cores - 1 script threads)
1727+
// -par=-n means "leave n cores free" (number of cores - n - 1 script threads)
1728+
script_threads += GetNumCores();
1729+
}
1730+
1731+
// Subtract 1 because the main thread counts towards the par threads
1732+
script_threads = std::max(script_threads - 1, 0);
1733+
1734+
// Number of script-checking threads <= MAX_SCRIPTCHECK_THREADS
1735+
script_threads = std::min(script_threads, MAX_SCRIPTCHECK_THREADS);
1736+
1737+
LogPrintf("Script verification uses %d additional threads\n", script_threads);
1738+
if (script_threads >= 1) {
1739+
g_parallel_script_checks = true;
1740+
for (int i = 0; i < script_threads; ++i) {
17361741
threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
1742+
}
17371743
}
17381744

17391745
std::vector<std::string> vSporkAddresses;

src/test/checkqueue_tests.cpp

+7-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include <sync.h>
66
#include <util.h>
77
#include <utiltime.h>
8-
#include <validation.h>
98

109
#include <test/test_dash.h>
1110
#include <checkqueue.h>
@@ -21,11 +20,10 @@
2120
#include <memory>
2221
#include <random.h>
2322

24-
// BasicTestingSetup not sufficient because nScriptCheckThreads is not set
25-
// otherwise.
2623
BOOST_FIXTURE_TEST_SUITE(checkqueue_tests, TestingSetup)
2724

2825
static const unsigned int QUEUE_BATCH_SIZE = 128;
26+
static const int SCRIPT_CHECK_THREADS = 3;
2927

3028
struct FakeCheck {
3129
bool operator()()
@@ -151,7 +149,7 @@ static void Correct_Queue_range(std::vector<size_t> range)
151149
{
152150
auto small_queue = std::unique_ptr<Correct_Queue>(new Correct_Queue {QUEUE_BATCH_SIZE});
153151
boost::thread_group tg;
154-
for (auto x = 0; x < nScriptCheckThreads; ++x) {
152+
for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) {
155153
tg.create_thread([&]{small_queue->Thread();});
156154
}
157155
// Make vChecks here to save on malloc (this test can be slow...)
@@ -217,7 +215,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure)
217215
auto fail_queue = std::unique_ptr<Failing_Queue>(new Failing_Queue {QUEUE_BATCH_SIZE});
218216

219217
boost::thread_group tg;
220-
for (auto x = 0; x < nScriptCheckThreads; ++x) {
218+
for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) {
221219
tg.create_thread([&]{fail_queue->Thread();});
222220
}
223221

@@ -249,7 +247,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure)
249247
{
250248
auto fail_queue = std::unique_ptr<Failing_Queue>(new Failing_Queue {QUEUE_BATCH_SIZE});
251249
boost::thread_group tg;
252-
for (auto x = 0; x < nScriptCheckThreads; ++x) {
250+
for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) {
253251
tg.create_thread([&]{fail_queue->Thread();});
254252
}
255253

@@ -277,7 +275,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck)
277275
{
278276
auto queue = std::unique_ptr<Unique_Queue>(new Unique_Queue {QUEUE_BATCH_SIZE});
279277
boost::thread_group tg;
280-
for (auto x = 0; x < nScriptCheckThreads; ++x) {
278+
for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) {
281279
tg.create_thread([&]{queue->Thread();});
282280

283281
}
@@ -317,7 +315,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory)
317315
{
318316
auto queue = std::unique_ptr<Memory_Queue>(new Memory_Queue {QUEUE_BATCH_SIZE});
319317
boost::thread_group tg;
320-
for (auto x = 0; x < nScriptCheckThreads; ++x) {
318+
for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) {
321319
tg.create_thread([&]{queue->Thread();});
322320
}
323321
for (size_t i = 0; i < 1000; ++i) {
@@ -349,7 +347,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup)
349347
auto queue = std::unique_ptr<FrozenCleanup_Queue>(new FrozenCleanup_Queue {QUEUE_BATCH_SIZE});
350348
boost::thread_group tg;
351349
bool fails = false;
352-
for (auto x = 0; x < nScriptCheckThreads; ++x) {
350+
for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) {
353351
tg.create_thread([&]{queue->Thread();});
354352
}
355353
std::thread t0([&]() {

src/test/test_dash.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,12 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
120120
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state)));
121121
}
122122
}
123-
nScriptCheckThreads = 3;
124-
for (int i=0; i < nScriptCheckThreads-1; i++)
123+
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
124+
constexpr int script_check_threads = 2;
125+
for (int i = 0; i < script_check_threads; ++i) {
125126
threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
127+
}
128+
g_parallel_script_checks = true;
126129
peerLogic.reset(new PeerLogicValidation(connman, scheduler, /*enable_bip61=*/true));
127130
}
128131

src/validation.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ CBlockIndex *pindexBestHeader = nullptr;
227227
Mutex g_best_block_mutex;
228228
std::condition_variable g_best_block_cv;
229229
uint256 g_best_block;
230-
int nScriptCheckThreads = 0;
230+
bool g_parallel_script_checks{false};
231231
std::atomic_bool fImporting(false);
232232
std::atomic_bool fReindex(false);
233233
bool fAddressIndex = false;
@@ -2151,7 +2151,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
21512151

21522152
CBlockUndo blockundo;
21532153

2154-
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : nullptr);
2154+
CCheckQueueControl<CScriptCheck> control(fScriptChecks && g_parallel_script_checks ? &scriptcheckqueue : nullptr);
21552155

21562156
std::vector<int> prevheights;
21572157
CAmount nFees = 0;
@@ -2264,9 +2264,10 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
22642264

22652265
std::vector<CScriptCheck> vChecks;
22662266
bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
2267-
if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, fCacheResults, txdata[i], nScriptCheckThreads ? &vChecks : nullptr))
2267+
if (fScriptChecks && !CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, fCacheResults, txdata[i], g_parallel_script_checks ? &vChecks : nullptr)) {
22682268
return error("ConnectBlock(): CheckInputs on %s failed with %s",
22692269
tx.GetHash().ToString(), FormatStateMessage(state));
2270+
}
22702271
control.Add(vChecks);
22712272
}
22722273

src/validation.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
7979
/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
8080
static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
8181

82-
/** Maximum number of script-checking threads allowed */
83-
static const int MAX_SCRIPTCHECK_THREADS = 16;
82+
/** Maximum number of dedicated script-checking threads allowed */
83+
static const int MAX_SCRIPTCHECK_THREADS = 15;
8484
/** -par default (number of script-checking threads, 0 = auto) */
8585
static const int DEFAULT_SCRIPTCHECK_THREADS = 0;
8686
/** Number of blocks that can be requested at any given time from a single peer. */
@@ -162,11 +162,14 @@ extern std::condition_variable g_best_block_cv;
162162
extern uint256 g_best_block;
163163
extern std::atomic_bool fImporting;
164164
extern std::atomic_bool fReindex;
165-
extern int nScriptCheckThreads;
166165
extern bool fAddressIndex;
167166
extern bool fTimestampIndex;
168167
extern bool fSpentIndex;
169168
extern bool fIsBareMultisigStd;
169+
/** Whether there are dedicated script-checking threads running.
170+
* False indicates all script checking is done on the main threadMessageHandler thread.
171+
*/
172+
extern bool g_parallel_script_checks;
170173
extern bool fRequireStandard;
171174
extern unsigned int nBytesPerSigOp;
172175
extern bool fCheckBlockIndex;

0 commit comments

Comments
 (0)