From 584d39d1c453b274da5e7cc6d06ded615ab70868 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Thu, 2 Mar 2023 17:15:55 +0800 Subject: [PATCH] perf: benchmark structure --- src/klotski_core/benchmark/benchmark.cc | 102 ++++-------------------- src/klotski_core/benchmark/benchmark.h | 25 ++++-- src/klotski_core/benchmark/chore.cc | 55 ++++++++++++- src/klotski_core/ffi/tmain.cc | 5 +- 4 files changed, 87 insertions(+), 100 deletions(-) diff --git a/src/klotski_core/benchmark/benchmark.cc b/src/klotski_core/benchmark/benchmark.cc index 2308550..6926917 100644 --- a/src/klotski_core/benchmark/benchmark.cc +++ b/src/klotski_core/benchmark/benchmark.cc @@ -1,11 +1,5 @@ -#include -#include #include "benchmark.h" #include "all_cases.h" -#include "short_code.h" -#include "common_code.h" - -#include using klotski::Benchmark; @@ -29,109 +23,45 @@ double Benchmark::all_cases(TIME format) noexcept { } double Benchmark::short_code_to_string(TIME format) noexcept { - /// data preparation - std::vector data; - data.reserve(klotski::SHORT_CODE_LIMIT); - for (uint32_t short_code = 0; short_code < klotski::SHORT_CODE_LIMIT; ++short_code) { - data.emplace_back(ShortCode::unsafe_create(short_code)); + if (!data_ready) { + return -1; // data no ready -> skip } - - /// start benchmark auto start = clock(); - for (const auto &short_code : data) { + for (const auto &short_code : all_short_codes) { short_code.to_string(); } - return time_format(start, format) / (double)data.size(); + return time_format(start, format) / (double)all_short_codes.size(); } double Benchmark::short_code_from_string(TIME format) noexcept { - /// data preparation - std::vector data; - data.reserve(klotski::SHORT_CODE_LIMIT); - for (uint32_t short_code = 0; short_code < klotski::SHORT_CODE_LIMIT; ++short_code) { - data.emplace_back(ShortCode::unsafe_create(short_code).to_string()); + if (!data_ready) { + return -1; // data no ready -> skip } - - /// start benchmark auto start = clock(); - for (auto &&short_code : data) { + for (auto &&short_code : all_short_codes_str) { ShortCode{std::forward(short_code)}; } - return time_format(start, format) / (double)data.size(); + return time_format(start, format) / (double)all_short_codes_str.size(); } double Benchmark::common_code_to_string(TIME format) noexcept { - /// data preparation - std::vector data; - data.reserve(klotski::ALL_CASES_SIZE_SUM); - for (uint64_t head = 0; head < 16; ++head) { - for (const auto &range : AllCases::fetch()[head]) { - data.emplace_back(CommonCode::unsafe_create(head << 32 | range)); - } + if (!data_ready) { + return -1; // data no ready -> skip } - - /// start benchmark auto start = clock(); - for (const auto &common_code : data) { + for (const auto &common_code : all_common_codes) { common_code.to_string(); } - return time_format(start, format) / (double)data.size(); + return time_format(start, format) / (double)all_common_codes.size(); } double Benchmark::common_code_from_string(TIME format) noexcept { - /// data preparation - std::vector data; - data.reserve(klotski::ALL_CASES_SIZE_SUM); - for (uint64_t head = 0; head < 16; ++head) { - for (const auto &range : AllCases::fetch()[head]) { - data.emplace_back( - CommonCode::unsafe_create(head << 32 | range).to_string() - ); - } - } - - /// start benchmark - auto start = clock(); - for (auto &&common_code : data) { - CommonCode{std::forward(common_code)}; - } - return time_format(start, format) / (double)data.size(); -} - -double Benchmark::common_code_to_string_shorten(TIME format) noexcept { - /// data preparation - std::vector data; - data.reserve(klotski::ALL_CASES_SIZE_SUM); - for (uint64_t head = 0; head < 16; ++head) { - for (const auto &range : AllCases::fetch()[head]) { - data.emplace_back(CommonCode::unsafe_create(head << 32 | range)); - } - } - - /// start benchmark - auto start = clock(); - for (const auto &common_code : data) { - common_code.to_string(true); + if (!data_ready) { + return -1; // data no ready -> skip } - return time_format(start, format) / (double)data.size(); -} - -double Benchmark::common_code_from_string_shorten(TIME format) noexcept { - /// data preparation - std::vector data; - data.reserve(klotski::ALL_CASES_SIZE_SUM); - for (uint64_t head = 0; head < 16; ++head) { - for (const auto &range : AllCases::fetch()[head]) { - data.emplace_back( - CommonCode::unsafe_create(head << 32 | range).to_string(true) - ); - } - } - - /// start benchmark auto start = clock(); - for (auto &&common_code : data) { + for (auto &&common_code : all_common_codes_str) { CommonCode{std::forward(common_code)}; } - return time_format(start, format) / (double)data.size(); + return time_format(start, format) / (double)all_common_codes_str.size(); } diff --git a/src/klotski_core/benchmark/benchmark.h b/src/klotski_core/benchmark/benchmark.h index c04fa45..f7bc604 100644 --- a/src/klotski_core/benchmark/benchmark.h +++ b/src/klotski_core/benchmark/benchmark.h @@ -8,24 +8,30 @@ /// returned according to the specified time format (seconds, milliseconds, /// microseconds, nanoseconds). -/// The test items are all multi-thread safe, but you should not run multiple -/// test items at the same time, which will lead to unstable tests in many ways, -/// such as changes in CPU turbo frequency. +/// The test items are all multi-thread safe(except `data_prepare`), but you +/// should not run multiple test items at the same time, which will lead to +/// unstable tests in many ways, such as changes in CPU turbo frequency. /// Pay attention to the two test items `basic_ranges` and `all_cases`, they can /// only be run once (the reason for the construction of static data), and cannot /// be run after other global related items. #include +#include +#include #include +#include "raw_code.h" +#include "short_code.h" +#include "common_code.h" + namespace klotski { class Benchmark { public: enum TIME { S, MS, US, NS }; - static uint32_t core_num() noexcept; + static void data_preparation() noexcept; static double warm_up(uint64_t count) noexcept; static double all_cases(TIME format = MS) noexcept; @@ -37,9 +43,6 @@ namespace klotski { static double common_code_to_string(TIME format = NS) noexcept; static double common_code_from_string(TIME format = NS) noexcept; - static double common_code_to_string_shorten(TIME format = NS) noexcept; - static double common_code_from_string_shorten(TIME format = NS) noexcept; - // static float codec_common_to_raw(TIME format = US); // static float codec_raw_to_common(TIME format = US); // static float codec_common_to_short(); @@ -47,8 +50,14 @@ namespace klotski { // static float codec_common_to_short_fast(); // static float codec_short_to_common_fast(); - private: + static bool data_ready; + static std::vector all_raw_codes; + static std::vector all_short_codes; + static std::vector all_common_codes; + static std::vector all_short_codes_str; + static std::vector all_common_codes_str; + static double time_format(clock_t start, TIME format) noexcept; }; } diff --git a/src/klotski_core/benchmark/chore.cc b/src/klotski_core/benchmark/chore.cc index 79639c6..ee101a6 100644 --- a/src/klotski_core/benchmark/chore.cc +++ b/src/klotski_core/benchmark/chore.cc @@ -1,11 +1,17 @@ #include #include "benchmark.h" +using klotski::RawCode; +using klotski::ShortCode; +using klotski::CommonCode; using klotski::Benchmark; -uint32_t Benchmark::core_num() noexcept { - return std::thread::hardware_concurrency(); -} +bool Benchmark::data_ready = false; +std::vector Benchmark::all_raw_codes; +std::vector Benchmark::all_short_codes; +std::vector Benchmark::all_common_codes; +std::vector Benchmark::all_short_codes_str; +std::vector Benchmark::all_common_codes_str; double Benchmark::warm_up(uint64_t count) noexcept { auto start = clock(); @@ -32,3 +38,46 @@ double Benchmark::time_format(clock_t start, TIME format) noexcept { } return time / CLOCKS_PER_SEC; } + +void Benchmark::data_preparation() noexcept { + if (Benchmark::data_ready) { + return; + } + + /// short code data preparation + std::vector tmp(klotski::SHORT_CODE_LIMIT); + std::iota(tmp.begin(), tmp.end(), 0); + + all_short_codes.reserve(klotski::SHORT_CODE_LIMIT); + for (auto &&short_code : tmp) { + all_short_codes.emplace_back(ShortCode::unsafe_create(short_code)); + } + + all_short_codes_str.reserve(klotski::SHORT_CODE_LIMIT); + for (auto &&short_code : all_short_codes) { + all_short_codes_str.emplace_back(short_code.to_string()); + } + + /// common code info preparation + all_common_codes.reserve(klotski::ALL_CASES_SIZE_SUM); + for (uint64_t head = 0; head < 16; ++head) { + for (const auto &range : AllCases::fetch()[head]) { + all_common_codes.emplace_back( + CommonCode::unsafe_create(head << 32 | range) + ); + } + } + + all_common_codes_str.reserve(klotski::ALL_CASES_SIZE_SUM); + for (auto &&common_code : all_common_codes) { + all_common_codes_str.emplace_back(common_code.to_string()); + } + + /// raw code data preparation + all_raw_codes.reserve(klotski::ALL_CASES_SIZE_SUM); + for (auto &&common_code : all_common_codes) { + all_raw_codes.emplace_back(common_code.to_raw_code()); + } + + Benchmark::data_ready = true; +} diff --git a/src/klotski_core/ffi/tmain.cc b/src/klotski_core/ffi/tmain.cc index b2314ca..46848eb 100644 --- a/src/klotski_core/ffi/tmain.cc +++ b/src/klotski_core/ffi/tmain.cc @@ -21,15 +21,14 @@ void tmain() { // std::cout << "basic ranges: " << Benchmark::basic_ranges() << "ms" << std::endl; // std::cout << "all cases: " << Benchmark::all_cases() << "ms" << std::endl; + Benchmark::data_preparation(); + std::cout << Benchmark::short_code_to_string() << "ns" << std::endl; std::cout << Benchmark::short_code_from_string() << "ns" << std::endl; std::cout << Benchmark::common_code_to_string() << "ns" << std::endl; std::cout << Benchmark::common_code_from_string() << "ns" << std::endl; - std::cout << Benchmark::common_code_to_string_shorten() << "ns" << std::endl; - std::cout << Benchmark::common_code_from_string_shorten() << "ns" << std::endl; - return; std::vector next;