diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index 4b9549488..fc3544efe 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -1,191 +1,182 @@ // Copyright (c) 2015-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include #include #include #include -const RegTestingSetup *g_testing_setup = nullptr; - void benchmark::ConsolePrinter::header() { std::cout << "# Benchmark, evals, iterations, total, min, max, median" << std::endl; } void benchmark::ConsolePrinter::result(const State &state) { auto results = state.m_elapsed_results; std::sort(results.begin(), results.end()); double total = state.m_num_iters * std::accumulate(results.begin(), results.end(), 0.0); double front = 0; double back = 0; double median = 0; if (!results.empty()) { front = results.front(); back = results.back(); size_t mid = results.size() / 2; median = results[mid]; if (0 == results.size() % 2) { median = (results[mid] + results[mid + 1]) / 2; } } std::cout << std::setprecision(6); std::cout << state.m_name << ", " << state.m_num_evals << ", " << state.m_num_iters << ", " << total << ", " << front << ", " << back << ", " << median << std::endl; } void benchmark::ConsolePrinter::footer() {} benchmark::PlotlyPrinter::PlotlyPrinter(std::string plotly_url, int64_t width, int64_t height) : m_plotly_url(plotly_url), m_width(width), m_height(height) {} void benchmark::PlotlyPrinter::header() { std::cout << "" << "" << "
" << ""; } void benchmark::JunitPrinter::header() { std::cout << "" << std::endl; } void benchmark::JunitPrinter::result(const State &state) { auto results = state.m_elapsed_results; double bench_duration = state.m_num_iters * std::accumulate(results.begin(), results.end(), 0.0); /* * Don't print the results now, we need them all to build the * node. */ bench_results.emplace_back(std::move(state.m_name), bench_duration); total_duration += bench_duration; } void benchmark::JunitPrinter::footer() { std::cout << std::setprecision(6); std::cout << "" << std::endl; for (const auto &result : bench_results) { std::cout << "" << std::endl; } std::cout << "" << std::endl; } benchmark::BenchRunner::BenchmarkMap &benchmark::BenchRunner::benchmarks() { static std::map benchmarks_map; return benchmarks_map; } benchmark::BenchRunner::BenchRunner(std::string name, benchmark::BenchFunction func, uint64_t num_iters_for_one_second) { benchmarks().insert( std::make_pair(name, Bench{func, num_iters_for_one_second})); } void benchmark::BenchRunner::RunAll(Printer &printer, uint64_t num_evals, double scaling, const std::string &filter, bool is_list_only) { if (!std::ratio_less_equal::value) { std::cerr << "WARNING: Clock precision is worse than microsecond - " "benchmarks may be less accurate!\n"; } #ifdef DEBUG std::cerr << "WARNING: This is a debug build - may result in slower " "benchmarks.\n"; #endif std::regex reFilter(filter); std::smatch baseMatch; printer.header(); for (const auto &p : benchmarks()) { - RegTestingSetup test{}; - assert(g_testing_setup == nullptr); - g_testing_setup = &test; - assert(::ChainActive().Height() == 0); - if (!std::regex_match(p.first, baseMatch, reFilter)) { - g_testing_setup = nullptr; continue; } uint64_t num_iters = static_cast(p.second.num_iters_for_one_second * scaling); if (0 == num_iters) { num_iters = 1; } State state(p.first, num_evals, num_iters, printer); if (!is_list_only) { p.second.func(state); } printer.result(state); - g_testing_setup = nullptr; } printer.footer(); } bool benchmark::State::UpdateTimer(const benchmark::time_point current_time) { if (m_start_time != time_point()) { std::chrono::duration diff = current_time - m_start_time; m_elapsed_results.push_back(diff.count() / m_num_iters); if (m_elapsed_results.size() == m_num_evals) { return false; } } m_num_iters_left = m_num_iters - 1; return true; } diff --git a/src/bench/bench.h b/src/bench/bench.h index 0e19afa5d..1974c0c0e 100644 --- a/src/bench/bench.h +++ b/src/bench/bench.h @@ -1,159 +1,155 @@ // Copyright (c) 2015-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_BENCH_BENCH_H #define BITCOIN_BENCH_BENCH_H #include #include #include #include #include #include #include -struct RegTestingSetup; -//! A pointer to the current testing setup -extern const RegTestingSetup *g_testing_setup; - // Simple micro-benchmarking framework; API mostly matches a subset of the // Google Benchmark framework (see https://github.com/google/benchmark) // Why not use the Google Benchmark framework? Because adding Yet Another // Dependency (that uses cmake as its build system and has lots of features we // don't need) isn't worth it. /* * Usage: static void CODE_TO_TIME(benchmark::State& state) { ... do any setup needed... while (state.KeepRunning()) { ... do stuff you want to time... } ... do any cleanup needed... } // default to running benchmark for 5000 iterations BENCHMARK(CODE_TO_TIME, 5000); */ namespace benchmark { // In case high_resolution_clock is steady, prefer that, otherwise use // steady_clock. struct best_clock { using hi_res_clock = std::chrono::high_resolution_clock; using steady_clock = std::chrono::steady_clock; using type = std::conditional::type; }; using clock = best_clock::type; using time_point = clock::time_point; using duration = clock::duration; class Printer; class State { public: std::string m_name; uint64_t m_num_iters_left; const uint64_t m_num_iters; const uint64_t m_num_evals; std::vector m_elapsed_results; time_point m_start_time; bool UpdateTimer(time_point finish_time); State(std::string name, uint64_t num_evals, double num_iters, Printer &printer) : m_name(name), m_num_iters_left(0), m_num_iters(num_iters), m_num_evals(num_evals) {} inline bool KeepRunning() { if (m_num_iters_left--) { return true; } bool result = UpdateTimer(clock::now()); // measure again so runtime of UpdateTimer is not included m_start_time = clock::now(); return result; } }; typedef std::function BenchFunction; class BenchRunner { struct Bench { BenchFunction func; uint64_t num_iters_for_one_second; }; typedef std::map BenchmarkMap; static BenchmarkMap &benchmarks(); public: BenchRunner(std::string name, BenchFunction func, uint64_t num_iters_for_one_second); static void RunAll(Printer &printer, uint64_t num_evals, double scaling, const std::string &filter, bool is_list_only); }; // interface to output benchmark results. class Printer { public: virtual ~Printer() {} virtual void header() = 0; virtual void result(const State &state) = 0; virtual void footer() = 0; }; // default printer to console, shows min, max, median. class ConsolePrinter : public Printer { public: void header() override; void result(const State &state) override; void footer() override; }; // creates box plot with plotly.js class PlotlyPrinter : public Printer { public: PlotlyPrinter(std::string plotly_url, int64_t width, int64_t height); void header() override; void result(const State &state) override; void footer() override; private: std::string m_plotly_url; int64_t m_width; int64_t m_height; }; // Junit compatible printer, allow to log durations on compatible CI class JunitPrinter : public Printer { public: void header() override; void result(const State &state) override; void footer() override; private: std::vector> bench_results; double total_duration; }; } // namespace benchmark // BENCHMARK(foo, num_iters_for_one_second) expands to: benchmark::BenchRunner // bench_11foo("foo", num_iterations); // Choose a num_iters_for_one_second that takes roughly 1 second. The goal is // that all benchmarks should take approximately // the same time, and scaling factor can be used that the total time is // appropriate for your system. #define BENCHMARK(n, num_iters_for_one_second) \ benchmark::BenchRunner BOOST_PP_CAT(bench_, BOOST_PP_CAT(__LINE__, n))( \ BOOST_PP_STRINGIZE(n), n, (num_iters_for_one_second)); #endif // BITCOIN_BENCH_BENCH_H diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp index 0d17e9a39..7cdeac02e 100644 --- a/src/bench/block_assemble.cpp +++ b/src/bench/block_assemble.cpp @@ -1,61 +1,62 @@ // Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include