Related (but not required for this PR), the below patch removing default value duplication would ensure the default work_threads_num
value doesn’t depend on argsmanager being used either:
0diff --git a/src/init.cpp b/src/init.cpp
1index 94a5a08463..61c6f060f1 100644
2--- a/src/init.cpp
3+++ b/src/init.cpp
4@@ -32,6 +32,7 @@
5 #include <interfaces/ipc.h>
6 #include <interfaces/mining.h>
7 #include <interfaces/node.h>
8+#include <kernel/chainstatemanager_opts.h>
9 #include <kernel/context.h>
10 #include <key.h>
11 #include <logging.h>
12diff --git a/src/kernel/chainstatemanager_opts.h b/src/kernel/chainstatemanager_opts.h
13index 1b605f3d55..95827c5d00 100644
14--- a/src/kernel/chainstatemanager_opts.h
15+++ b/src/kernel/chainstatemanager_opts.h
16@@ -8,6 +8,7 @@
17 #include <kernel/notifications_interface.h>
18
19 #include <arith_uint256.h>
20+#include <common/system.h>
21 #include <dbwrapper.h>
22 #include <script/sigcache.h>
23 #include <txdb.h>
24@@ -23,6 +24,8 @@ class ValidationSignals;
25
26 static constexpr bool DEFAULT_CHECKPOINTS_ENABLED{true};
27 static constexpr auto DEFAULT_MAX_TIP_AGE{24h};
28+/** -par default (number of script-checking threads) */
29+static const int DEFAULT_SCRIPTCHECK_THREADS{GetNumCores() - 1};
30
31 namespace kernel {
32
33@@ -48,7 +51,7 @@ struct ChainstateManagerOpts {
34 Notifications& notifications;
35 ValidationSignals* signals{nullptr};
36 //! Number of script check worker threads. Zero means no parallel verification.
37- int worker_threads_num{0};
38+ int worker_threads_num{DEFAULT_SCRIPTCHECK_THREADS};
39 size_t script_execution_cache_bytes{DEFAULT_SCRIPT_EXECUTION_CACHE_BYTES};
40 size_t signature_cache_bytes{DEFAULT_SIGNATURE_CACHE_BYTES};
41 };
42diff --git a/src/node/chainstatemanager_args.cpp b/src/node/chainstatemanager_args.cpp
43index cdc8bdd43e..e4a2546b2b 100644
44--- a/src/node/chainstatemanager_args.cpp
45+++ b/src/node/chainstatemanager_args.cpp
46@@ -53,14 +53,13 @@ util::Result<void> ApplyArgsManOptions(const ArgsManager& args, ChainstateManage
47 ReadDatabaseArgs(args, opts.coins_db);
48 ReadCoinsViewArgs(args, opts.coins_view);
49
50- int script_threads = args.GetIntArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
51- if (script_threads <= 0) {
52+ if (auto script_threads{args.GetIntArg("-par")}) {
53 // -par=0 means autodetect (number of cores - 1 script threads)
54 // -par=-n means "leave n cores free" (number of cores - n - 1 script threads)
55- script_threads += GetNumCores();
56+ if (*script_threads <= 0) *script_threads += GetNumCores();
57+ // Subtract 1 because the main thread counts towards the par threads.
58+ opts.worker_threads_num = *script_threads - 1;
59 }
60- // Subtract 1 because the main thread counts towards the par threads.
61- opts.worker_threads_num = script_threads - 1;
62
63 if (auto max_size = args.GetIntArg("-maxsigcachesize")) {
64 // 1. When supplied with a max_size of 0, both the signature cache and
65diff --git a/src/node/chainstatemanager_args.h b/src/node/chainstatemanager_args.h
66index af13aa8d3c..701515953e 100644
67--- a/src/node/chainstatemanager_args.h
68+++ b/src/node/chainstatemanager_args.h
69@@ -10,9 +10,6 @@
70
71 class ArgsManager;
72
73-/** -par default (number of script-checking threads, 0 = auto) */
74-static constexpr int DEFAULT_SCRIPTCHECK_THREADS{0};
75-
76 namespace node {
77 [[nodiscard]] util::Result<void> ApplyArgsManOptions(const ArgsManager& args, ChainstateManager::Options& opts);
78 } // namespace node