mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
Merge #6250: backport: Merge bitcoin#22217, 23025, 22362
bd67f80634
Merge bitcoin/bitcoin#22362: Drop only invalid entries when reading banlist.json (W. J. van der Laan)8b3a486702
Merge bitcoin/bitcoin#23025: bench: update nanobench add `-min_time` (W. J. van der Laan)d7a20b3ee6
Merge bitcoin/bitcoin#22217: refactor: Avoid wallet code writing node settings file (Samuel Dobson) Pull request description: btc backport ACKs for top commit: knst: utACKbd67f80634
UdjinM6: utACKbd67f80634
Tree-SHA512: c487760c7b4946c21103978625076dd276344c831e99452031fae9b5c6cf954a1a0d3109725ab10f3d6837a5fd1833886a7e28c88b28429c6638c82f06f54f3d
This commit is contained in:
commit
c200175ebf
@ -4,15 +4,20 @@
|
|||||||
|
|
||||||
#include <bench/bench.h>
|
#include <bench/bench.h>
|
||||||
|
|
||||||
#include <chainparams.h>
|
|
||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
#include <test/util/setup_common.h>
|
#include <test/util/setup_common.h>
|
||||||
#include <validation.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <chrono>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
|
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
|
||||||
|
|
||||||
@ -66,6 +71,12 @@ void benchmark::BenchRunner::RunAll(const Args& args)
|
|||||||
|
|
||||||
Bench bench;
|
Bench bench;
|
||||||
bench.name(p.first);
|
bench.name(p.first);
|
||||||
|
if (args.min_time > 0ms) {
|
||||||
|
// convert to nanos before dividing to reduce rounding errors
|
||||||
|
std::chrono::nanoseconds min_time_ns = args.min_time;
|
||||||
|
bench.minEpochTime(min_time_ns / bench.epochs());
|
||||||
|
}
|
||||||
|
|
||||||
if (args.asymptote.empty()) {
|
if (args.asymptote.empty()) {
|
||||||
p.second(bench);
|
p.second(bench);
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,11 +42,12 @@ using ankerl::nanobench::Bench;
|
|||||||
typedef std::function<void(Bench&)> BenchFunction;
|
typedef std::function<void(Bench&)> BenchFunction;
|
||||||
|
|
||||||
struct Args {
|
struct Args {
|
||||||
std::string regex_filter;
|
|
||||||
bool is_list_only;
|
bool is_list_only;
|
||||||
|
std::chrono::milliseconds min_time;
|
||||||
std::vector<double> asymptote;
|
std::vector<double> asymptote;
|
||||||
fs::path output_csv;
|
fs::path output_csv;
|
||||||
fs::path output_json;
|
fs::path output_json;
|
||||||
|
std::string regex_filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BenchRunner
|
class BenchRunner
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <bench/bench.h>
|
#include <bench/bench.h>
|
||||||
|
|
||||||
|
#include <clientversion.h>
|
||||||
#include <crypto/sha256.h>
|
#include <crypto/sha256.h>
|
||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
#include <stacktraces.h>
|
#include <stacktraces.h>
|
||||||
@ -11,16 +12,23 @@
|
|||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
|
|
||||||
#include <bls/bls.h>
|
#include <bls/bls.h>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
static const char* DEFAULT_BENCH_FILTER = ".*";
|
static const char* DEFAULT_BENCH_FILTER = ".*";
|
||||||
|
static constexpr int64_t DEFAULT_MIN_TIME_MS{10};
|
||||||
|
|
||||||
static void SetupBenchArgs(ArgsManager& argsman)
|
static void SetupBenchArgs(ArgsManager& argsman)
|
||||||
{
|
{
|
||||||
SetupHelpOptions(argsman);
|
SetupHelpOptions(argsman);
|
||||||
|
|
||||||
argsman.AddArg("-asymptote=n1,n2,n3,...", "Test asymptotic growth of the runtime of an algorithm, if supported by the benchmark", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
argsman.AddArg("-asymptote=<n1,n2,n3,...>", "Test asymptotic growth of the runtime of an algorithm, if supported by the benchmark", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||||
argsman.AddArg("-filter=<regex>", strprintf("Regular expression filter to select benchmark by name (default: %s)", DEFAULT_BENCH_FILTER), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
argsman.AddArg("-filter=<regex>", strprintf("Regular expression filter to select benchmark by name (default: %s)", DEFAULT_BENCH_FILTER), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||||
argsman.AddArg("-list", "List benchmarks without executing them", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
argsman.AddArg("-list", "List benchmarks without executing them", ArgsManager::ALLOW_BOOL, OptionsCategory::OPTIONS);
|
||||||
|
argsman.AddArg("-min_time=<milliseconds>", strprintf("Minimum runtime per benchmark, in milliseconds (default: %d)", DEFAULT_MIN_TIME_MS), ArgsManager::ALLOW_INT, OptionsCategory::OPTIONS);
|
||||||
argsman.AddArg("-output_csv=<output.csv>", "Generate CSV file with the most important benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
argsman.AddArg("-output_csv=<output.csv>", "Generate CSV file with the most important benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||||
argsman.AddArg("-output_json=<output.json>", "Generate JSON file with all benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
argsman.AddArg("-output_json=<output.json>", "Generate JSON file with all benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||||
}
|
}
|
||||||
@ -50,16 +58,62 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (HelpRequested(argsman)) {
|
if (HelpRequested(argsman)) {
|
||||||
std::cout << argsman.GetHelpMessage();
|
std::cout << "Usage: bench_dash [options]\n"
|
||||||
|
"\n"
|
||||||
|
<< argsman.GetHelpMessage()
|
||||||
|
<< "Description:\n"
|
||||||
|
"\n"
|
||||||
|
" bench_dash executes microbenchmarks. The quality of the benchmark results\n"
|
||||||
|
" highly depend on the stability of the machine. It can sometimes be difficult\n"
|
||||||
|
" to get stable, repeatable results, so here are a few tips:\n"
|
||||||
|
"\n"
|
||||||
|
" * Use pyperf [1] to disable frequency scaling, turbo boost etc. For best\n"
|
||||||
|
" results, use CPU pinning and CPU isolation (see [2]).\n"
|
||||||
|
"\n"
|
||||||
|
" * Each call of run() should do exactly the same work. E.g. inserting into\n"
|
||||||
|
" a std::vector doesn't do that as it will reallocate on certain calls. Make\n"
|
||||||
|
" sure each run has exactly the same preconditions.\n"
|
||||||
|
"\n"
|
||||||
|
" * If results are still not reliable, increase runtime with e.g.\n"
|
||||||
|
" -min_time=5000 to let a benchmark run for at least 5 seconds.\n"
|
||||||
|
"\n"
|
||||||
|
" * bench_dash uses nanobench [3] for which there is extensive\n"
|
||||||
|
" documentation available online.\n"
|
||||||
|
"\n"
|
||||||
|
"Environment Variables:\n"
|
||||||
|
"\n"
|
||||||
|
" To attach a profiler you can run a benchmark in endless mode. This can be\n"
|
||||||
|
" done with the environment variable NANOBENCH_ENDLESS. E.g. like so:\n"
|
||||||
|
"\n"
|
||||||
|
" NANOBENCH_ENDLESS=MuHash ./bench_dash -filter=MuHash\n"
|
||||||
|
"\n"
|
||||||
|
" In rare cases it can be useful to suppress stability warnings. This can be\n"
|
||||||
|
" done with the environment variable NANOBENCH_SUPPRESS_WARNINGS, e.g:\n"
|
||||||
|
"\n"
|
||||||
|
" NANOBENCH_SUPPRESS_WARNINGS=1 ./bench_dash\n"
|
||||||
|
"\n"
|
||||||
|
"Notes:\n"
|
||||||
|
"\n"
|
||||||
|
" 1. pyperf\n"
|
||||||
|
" https://github.com/psf/pyperf\n"
|
||||||
|
"\n"
|
||||||
|
" 2. CPU pinning & isolation\n"
|
||||||
|
" https://pyperf.readthedocs.io/en/latest/system.html\n"
|
||||||
|
"\n"
|
||||||
|
" 3. nanobench\n"
|
||||||
|
" https://github.com/martinus/nanobench\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
benchmark::Args args;
|
benchmark::Args args;
|
||||||
args.regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER);
|
|
||||||
args.is_list_only = argsman.GetBoolArg("-list", false);
|
|
||||||
args.asymptote = parseAsymptote(argsman.GetArg("-asymptote", ""));
|
args.asymptote = parseAsymptote(argsman.GetArg("-asymptote", ""));
|
||||||
|
args.is_list_only = argsman.GetBoolArg("-list", false);
|
||||||
|
args.min_time = std::chrono::milliseconds(argsman.GetArg("-min_time", DEFAULT_MIN_TIME_MS));
|
||||||
args.output_csv = fs::PathFromString(argsman.GetArg("-output_csv", ""));
|
args.output_csv = fs::PathFromString(argsman.GetArg("-output_csv", ""));
|
||||||
args.output_json = fs::PathFromString(argsman.GetArg("-output_json", ""));
|
args.output_json = fs::PathFromString(argsman.GetArg("-output_json", ""));
|
||||||
|
args.regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER);
|
||||||
|
|
||||||
benchmark::BenchRunner::RunAll(args);
|
benchmark::BenchRunner::RunAll(args);
|
||||||
|
|
||||||
|
@ -249,9 +249,9 @@ static void MuHash(benchmark::Bench& bench)
|
|||||||
{
|
{
|
||||||
MuHash3072 acc;
|
MuHash3072 acc;
|
||||||
unsigned char key[32] = {0};
|
unsigned char key[32] = {0};
|
||||||
int i = 0;
|
uint32_t i = 0;
|
||||||
bench.run([&] {
|
bench.run([&] {
|
||||||
key[0] = ++i;
|
key[0] = ++i & 0xFF;
|
||||||
acc *= MuHash3072(key);
|
acc *= MuHash3072(key);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -273,10 +273,6 @@ static void MuHashDiv(benchmark::Bench& bench)
|
|||||||
FastRandomContext rng(true);
|
FastRandomContext rng(true);
|
||||||
MuHash3072 muhash{rng.randbytes(32)};
|
MuHash3072 muhash{rng.randbytes(32)};
|
||||||
|
|
||||||
for (size_t i = 0; i < bench.epochIterations(); ++i) {
|
|
||||||
acc *= muhash;
|
|
||||||
}
|
|
||||||
|
|
||||||
bench.run([&] {
|
bench.run([&] {
|
||||||
acc /= muhash;
|
acc /= muhash;
|
||||||
});
|
});
|
||||||
|
@ -20,19 +20,17 @@ static void EvictionProtectionCommon(
|
|||||||
{
|
{
|
||||||
using Candidates = std::vector<NodeEvictionCandidate>;
|
using Candidates = std::vector<NodeEvictionCandidate>;
|
||||||
FastRandomContext random_context{true};
|
FastRandomContext random_context{true};
|
||||||
bench.warmup(100).epochIterations(1100);
|
|
||||||
|
|
||||||
Candidates candidates{GetRandomNodeEvictionCandidates(num_candidates, random_context)};
|
Candidates candidates{GetRandomNodeEvictionCandidates(num_candidates, random_context)};
|
||||||
for (auto& c : candidates) {
|
for (auto& c : candidates) {
|
||||||
candidate_setup_fn(c);
|
candidate_setup_fn(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Candidates> copies{
|
|
||||||
static_cast<size_t>(bench.epochs() * bench.epochIterations()), candidates};
|
|
||||||
size_t i{0};
|
|
||||||
bench.run([&] {
|
bench.run([&] {
|
||||||
ProtectEvictionCandidatesByRatio(copies.at(i));
|
// creating a copy has an overhead of about 3%, so it does not influence the benchmark results much.
|
||||||
++i;
|
auto copy = candidates;
|
||||||
|
ProtectEvictionCandidatesByRatio(copy);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,16 +13,16 @@ static void RollingBloom(benchmark::Bench& bench)
|
|||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
bench.run([&] {
|
bench.run([&] {
|
||||||
count++;
|
count++;
|
||||||
data[0] = count;
|
data[0] = count & 0xFF;
|
||||||
data[1] = count >> 8;
|
data[1] = (count >> 8) & 0xFF;
|
||||||
data[2] = count >> 16;
|
data[2] = (count >> 16) & 0xFF;
|
||||||
data[3] = count >> 24;
|
data[3] = (count >> 24) & 0xFF;
|
||||||
filter.insert(data);
|
filter.insert(data);
|
||||||
|
|
||||||
data[0] = count >> 24;
|
data[0] = (count >> 24) & 0xFF;
|
||||||
data[1] = count >> 16;
|
data[1] = (count >> 16) & 0xFF;
|
||||||
data[2] = count >> 8;
|
data[2] = (count >> 8) & 0xFF;
|
||||||
data[3] = count;
|
data[3] = count & 0xFF;
|
||||||
filter.contains(data);
|
filter.contains(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -285,11 +285,18 @@ public:
|
|||||||
//! Run function after given number of seconds. Cancel any previous calls with same name.
|
//! Run function after given number of seconds. Cancel any previous calls with same name.
|
||||||
virtual void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) = 0;
|
virtual void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) = 0;
|
||||||
|
|
||||||
|
//! Get settings value.
|
||||||
|
virtual util::SettingsValue getSetting(const std::string& arg) = 0;
|
||||||
|
|
||||||
|
//! Get list of settings values.
|
||||||
|
virtual std::vector<util::SettingsValue> getSettingsList(const std::string& arg) = 0;
|
||||||
|
|
||||||
//! Return <datadir>/settings.json setting value.
|
//! Return <datadir>/settings.json setting value.
|
||||||
virtual util::SettingsValue getRwSetting(const std::string& name) = 0;
|
virtual util::SettingsValue getRwSetting(const std::string& name) = 0;
|
||||||
|
|
||||||
//! Write a setting to <datadir>/settings.json.
|
//! Write a setting to <datadir>/settings.json. Optionally just update the
|
||||||
virtual bool updateRwSetting(const std::string& name, const util::SettingsValue& value) = 0;
|
//! setting in memory and do not write the file.
|
||||||
|
virtual bool updateRwSetting(const std::string& name, const util::SettingsValue& value, bool write=true) = 0;
|
||||||
|
|
||||||
//! Synchronously send transactionAddedToMempool notifications about all
|
//! Synchronously send transactionAddedToMempool notifications about all
|
||||||
//! current mempool transactions to the specified handler and return after
|
//! current mempool transactions to the specified handler and return after
|
||||||
|
@ -971,6 +971,14 @@ public:
|
|||||||
{
|
{
|
||||||
RPCRunLater(name, std::move(fn), seconds);
|
RPCRunLater(name, std::move(fn), seconds);
|
||||||
}
|
}
|
||||||
|
util::SettingsValue getSetting(const std::string& name) override
|
||||||
|
{
|
||||||
|
return gArgs.GetSetting(name);
|
||||||
|
}
|
||||||
|
std::vector<util::SettingsValue> getSettingsList(const std::string& name) override
|
||||||
|
{
|
||||||
|
return gArgs.GetSettingsList(name);
|
||||||
|
}
|
||||||
util::SettingsValue getRwSetting(const std::string& name) override
|
util::SettingsValue getRwSetting(const std::string& name) override
|
||||||
{
|
{
|
||||||
util::SettingsValue result;
|
util::SettingsValue result;
|
||||||
@ -981,7 +989,7 @@ public:
|
|||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
bool updateRwSetting(const std::string& name, const util::SettingsValue& value) override
|
bool updateRwSetting(const std::string& name, const util::SettingsValue& value, bool write) override
|
||||||
{
|
{
|
||||||
gArgs.LockSettings([&](util::Settings& settings) {
|
gArgs.LockSettings([&](util::Settings& settings) {
|
||||||
if (value.isNull()) {
|
if (value.isNull()) {
|
||||||
@ -990,7 +998,7 @@ public:
|
|||||||
settings.rw_settings[name] = value;
|
settings.rw_settings[name] = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return gArgs.WriteSettingsFile();
|
return !write || gArgs.WriteSettingsFile();
|
||||||
}
|
}
|
||||||
void requestMempoolTransactions(Notifications& notifications) override
|
void requestMempoolTransactions(Notifications& notifications) override
|
||||||
{
|
{
|
||||||
|
@ -225,6 +225,7 @@ protected:
|
|||||||
*/
|
*/
|
||||||
bool UseDefaultSection(const std::string& arg) const EXCLUSIVE_LOCKS_REQUIRED(cs_args);
|
bool UseDefaultSection(const std::string& arg) const EXCLUSIVE_LOCKS_REQUIRED(cs_args);
|
||||||
|
|
||||||
|
public:
|
||||||
/**
|
/**
|
||||||
* Get setting value.
|
* Get setting value.
|
||||||
*
|
*
|
||||||
@ -239,7 +240,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
std::vector<util::SettingsValue> GetSettingsList(const std::string& arg) const;
|
std::vector<util::SettingsValue> GetSettingsList(const std::string& arg) const;
|
||||||
|
|
||||||
public:
|
|
||||||
ArgsManager();
|
ArgsManager();
|
||||||
~ArgsManager();
|
~ArgsManager();
|
||||||
|
|
||||||
|
@ -57,18 +57,20 @@ bool VerifyWallets(interfaces::Chain& chain)
|
|||||||
options.require_existing = true;
|
options.require_existing = true;
|
||||||
options.verify = false;
|
options.verify = false;
|
||||||
if (MakeWalletDatabase("", options, status, error_string)) {
|
if (MakeWalletDatabase("", options, status, error_string)) {
|
||||||
gArgs.LockSettings([&](util::Settings& settings) {
|
util::SettingsValue wallets(util::SettingsValue::VARR);
|
||||||
util::SettingsValue wallets(util::SettingsValue::VARR);
|
wallets.push_back(""); // Default wallet name is ""
|
||||||
wallets.push_back(""); // Default wallet name is ""
|
// Pass write=false because no need to write file and probably
|
||||||
settings.rw_settings["wallet"] = wallets;
|
// better not to. If unnamed wallet needs to be added next startup
|
||||||
});
|
// and the setting is empty, this code will just run again.
|
||||||
|
chain.updateRwSetting("wallet", wallets, /* write= */ false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep track of each wallet absolute path to detect duplicates.
|
// Keep track of each wallet absolute path to detect duplicates.
|
||||||
std::set<fs::path> wallet_paths;
|
std::set<fs::path> wallet_paths;
|
||||||
|
|
||||||
for (const auto& wallet_file : gArgs.GetArgs("-wallet")) {
|
for (const auto& wallet : chain.getSettingsList("wallet")) {
|
||||||
|
const auto& wallet_file = wallet.get_str();
|
||||||
const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(wallet_file));
|
const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(wallet_file));
|
||||||
|
|
||||||
if (!wallet_paths.insert(path).second) {
|
if (!wallet_paths.insert(path).second) {
|
||||||
@ -98,7 +100,8 @@ bool LoadWallets(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoi
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
std::set<fs::path> wallet_paths;
|
std::set<fs::path> wallet_paths;
|
||||||
for (const std::string& name : gArgs.GetArgs("-wallet")) {
|
for (const auto& wallet : chain.getSettingsList("wallet")) {
|
||||||
|
const auto& name = wallet.get_str();
|
||||||
if (!wallet_paths.insert(fs::PathFromString(name)).second) {
|
if (!wallet_paths.insert(fs::PathFromString(name)).second) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user