diff --git a/src/klotski_core/benchmark/benchmark.cc b/src/klotski_core/benchmark/benchmark.cc index 570d042..2308550 100644 --- a/src/klotski_core/benchmark/benchmark.cc +++ b/src/klotski_core/benchmark/benchmark.cc @@ -1,9 +1,15 @@ +#include +#include #include "benchmark.h" #include "all_cases.h" +#include "short_code.h" +#include "common_code.h" + +#include using klotski::Benchmark; -float Benchmark::basic_ranges(TIME format) { +double Benchmark::basic_ranges(TIME format) noexcept { if (BasicRanges::status() != BasicRanges::NO_INIT) { return -1; // data already built -> skip } @@ -12,7 +18,7 @@ float Benchmark::basic_ranges(TIME format) { return time_format(start, format); } -float Benchmark::all_cases(TIME format) { +double Benchmark::all_cases(TIME format) noexcept { if (AllCases::status() != AllCases::NO_INIT) { return -1; // data already built -> skip } @@ -21,3 +27,111 @@ float Benchmark::all_cases(TIME format) { AllCases::build(); return time_format(start, format); } + +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)); + } + + /// start benchmark + auto start = clock(); + for (const auto &short_code : data) { + short_code.to_string(); + } + return time_format(start, format) / (double)data.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()); + } + + /// start benchmark + auto start = clock(); + for (auto &&short_code : data) { + ShortCode{std::forward(short_code)}; + } + return time_format(start, format) / (double)data.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)); + } + } + + /// start benchmark + auto start = clock(); + for (const auto &common_code : data) { + common_code.to_string(); + } + return time_format(start, format) / (double)data.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); + } + 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) { + CommonCode{std::forward(common_code)}; + } + return time_format(start, format) / (double)data.size(); +} diff --git a/src/klotski_core/benchmark/benchmark.h b/src/klotski_core/benchmark/benchmark.h index c48bfb0..c04fa45 100644 --- a/src/klotski_core/benchmark/benchmark.h +++ b/src/klotski_core/benchmark/benchmark.h @@ -14,9 +14,10 @@ /// 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 short code related items. +/// be run after other global related items. #include +#include namespace klotski { class Benchmark { @@ -24,10 +25,30 @@ namespace klotski { enum TIME { S, MS, US, NS }; - static float all_cases(TIME format = MS); - static float basic_ranges(TIME format = MS); + static uint32_t core_num() noexcept; + static double warm_up(uint64_t count) noexcept; + + static double all_cases(TIME format = MS) noexcept; + static double basic_ranges(TIME format = MS) noexcept; + + static double short_code_to_string(TIME format = NS) noexcept; + static double short_code_from_string(TIME format = NS) noexcept; + + 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(); +// static float codec_short_to_common(); +// static float codec_common_to_short_fast(); +// static float codec_short_to_common_fast(); + private: - static float time_format(clock_t start, enum TIME format); + 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 0d2bd1c..79639c6 100644 --- a/src/klotski_core/benchmark/chore.cc +++ b/src/klotski_core/benchmark/chore.cc @@ -1,21 +1,33 @@ +#include #include "benchmark.h" using klotski::Benchmark; -float Benchmark::time_format(clock_t start, TIME format) { - auto time = float(clock() - start); +uint32_t Benchmark::core_num() noexcept { + return std::thread::hardware_concurrency(); +} + +double Benchmark::warm_up(uint64_t count) noexcept { + auto start = clock(); + volatile uint64_t tmp = 0; + for (; tmp < count; ++tmp); + return time_format(start, US); +} + +double Benchmark::time_format(clock_t start, TIME format) noexcept { + auto time = double(clock() - start); switch (format) { case S: - time *= float(1); + time *= double(1); break; case MS: - time *= float(1000); + time *= double(1000); break; case US: - time *= float(1000 * 1000); + time *= double(1000 * 1000); break; case NS: - time *= float(1000 * 1000 * 1000); + time *= double(1000 * 1000 * 1000); break; } return time / CLOCKS_PER_SEC; diff --git a/src/klotski_core/ffi/tmain.cc b/src/klotski_core/ffi/tmain.cc index e471b0d..b2314ca 100644 --- a/src/klotski_core/ffi/tmain.cc +++ b/src/klotski_core/ffi/tmain.cc @@ -16,8 +16,19 @@ using klotski::Benchmark; void tmain() { // printf("tmain start\n"); - std::cout << "basic ranges: " << Benchmark::basic_ranges() << "ms" << std::endl; - std::cout << "all cases: " << Benchmark::all_cases() << "ms" << std::endl; +// std::cout << "warm up: " << Benchmark::warm_up(1000000) << "us" << std::endl; + +// std::cout << "basic ranges: " << Benchmark::basic_ranges() << "ms" << std::endl; +// std::cout << "all cases: " << Benchmark::all_cases() << "ms" << std::endl; + + 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;