From ca63237dfd3d85303ebfefe90269fd7dc5bf3f32 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sat, 18 May 2024 22:52:55 +0800 Subject: [PATCH] perf: optimize string encoding of ShortCode --- src/core/benchmark/codec.cc | 135 ++++++++++-------- src/core/short_code/internal/serialize.cc | 16 +-- .../short_code/internal/serialize_chars.h | 20 +-- src/core/short_code/short_code.h | 2 +- 4 files changed, 96 insertions(+), 77 deletions(-) diff --git a/src/core/benchmark/codec.cc b/src/core/benchmark/codec.cc index b984925..60da97c 100644 --- a/src/core/benchmark/codec.cc +++ b/src/core/benchmark/codec.cc @@ -48,59 +48,28 @@ std::vector common_code_samples(uint64_t num) { } -// std::vector select_codes(uint64_t num) { -// auto codes = all_common_codes(); -// -// // return {codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411]}; -// // std::array samples = { -// std::vector samples = { -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// codes[343], codes[666], codes[114514], codes[35324], codes[123454], codes[76453], codes[93411], -// }; -// -// return {samples.begin(), samples.begin() + num}; -// } +std::vector short_code_samples(uint64_t num) { + + uint32_t part_size = klotski::codec::SHORT_CODE_LIMIT / num; + + // uint64_t offset = 0; + uint32_t offset = part_size / 2; + + std::vector result; + + for (uint32_t i = 0; i < num; ++i) { + uint32_t index = i * part_size + offset; + // // std::cout << "index = " << index << std::endl; + + // uint64_t kk[] {343, 666, 114514, 35324, 123454, 76453, 93411}; + // uint64_t index = kk[i % 7]; + + result.emplace_back(index); + } + + return result; + +} std::vector str_common_codes(uint64_t num, bool shorten) { // auto src = select_codes(num); @@ -116,6 +85,20 @@ std::vector str_common_codes(uint64_t num, bool shorten) { return codes; } +std::vector str_short_codes(uint64_t num) { + + auto src = short_code_samples(num); + + std::vector codes; + + codes.reserve(src.size()); + for (auto x : src) { + codes.emplace_back(klotski::codec::ShortCode::unsafe_create(x).to_string()); + } + + return codes; +} + static void CommonCodeSerialize(benchmark::State &state) { // common_code_samples(8); @@ -174,10 +157,48 @@ static void CommonCodeDeserializeShorten(benchmark::State &state) { } -BENCHMARK(CommonCodeSerialize)->Range(8, 256); -BENCHMARK(CommonCodeDeserialize)->Range(8, 256); -BENCHMARK(CommonCodeSerializeShorten)->Range(8, 256); -BENCHMARK(CommonCodeDeserializeShorten)->Range(8, 256); +static void ShortCodeSerialize(benchmark::State &state) { + std::vector samples = short_code_samples(state.range(0)); + + for (auto _ : state) { + + for (const auto code : samples) { + volatile auto ret = klotski::codec::ShortCode::string_encode(code); + } + + } + + state.SetItemsProcessed(state.iterations() * state.range(0)); + +} + +static void ShortCodeDeserialize(benchmark::State &state) { + + const auto tmp = str_short_codes(state.range(0)); + + const std::vector samples {tmp.begin(), tmp.end()}; + + for (auto _ : state) { + + for (const auto code : samples) { + + volatile auto ret = klotski::codec::ShortCode::string_decode(code); + + } + + } + + state.SetItemsProcessed(state.iterations() * state.range(0)); + +} + +// BENCHMARK(CommonCodeSerialize)->Range(8, 256); +// BENCHMARK(CommonCodeDeserialize)->Range(8, 256); +// BENCHMARK(CommonCodeSerializeShorten)->Range(8, 256); +// BENCHMARK(CommonCodeDeserializeShorten)->Range(8, 256); + +BENCHMARK(ShortCodeSerialize)->Range(8, 256); +BENCHMARK(ShortCodeDeserialize)->Range(8, 256); // static void CommonCodeDecode(benchmark::State &state) { // const auto tmp = str_common_codes(state.range(0)); diff --git a/src/core/short_code/internal/serialize.cc b/src/core/short_code/internal/serialize.cc index 2795ca3..386f6d8 100644 --- a/src/core/short_code/internal/serialize.cc +++ b/src/core/short_code/internal/serialize.cc @@ -4,28 +4,24 @@ using klotski::codec::ShortCode; std::string ShortCode::string_encode(uint32_t short_code) { - char result[6]; - result[5] = '\0'; // string ending flag + char result[5]; for (int n = 0; n < 5; ++n) { result[4 - n] = SHORT_CODE_TABLE[short_code & 0b11111]; short_code >>= 5; } - return result; + return {result, result + 5}; } -std::optional ShortCode::string_decode(const std::string &short_code) { +std::optional ShortCode::string_decode(const std::string_view short_code) { if (short_code.length() != 5) { return std::nullopt; // invalid string length } - uint64_t result = 0; + uint32_t result = 0; for (auto bit : short_code) { - result <<= 5; - if (bit >= 'a' && bit <= 'z') { - bit -= 32; // convert to uppercase - } - if (bit < '1' || bit > 'Z') { // invalid characters + if (bit < '1' || bit > 'z') { // invalid characters return std::nullopt; } + result <<= 5; result += (bit = SHORT_CODE_TABLE_REV[bit - 49]); // table convert if (bit == -1) { // invalid character return std::nullopt; diff --git a/src/core/short_code/internal/serialize_chars.h b/src/core/short_code/internal/serialize_chars.h index 07b1234..fce6ca6 100644 --- a/src/core/short_code/internal/serialize_chars.h +++ b/src/core/short_code/internal/serialize_chars.h @@ -15,11 +15,9 @@ /// | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z` | /// /// ------------------------------------------------- /// -#include - namespace klotski::codec { -constexpr int8_t SHORT_CODE_TABLE[32] { +constexpr char SHORT_CODE_TABLE[32] { '1', '2', '3', '4', '5', '6', '7', '8', '9', // skip `0` 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // skip `I` 'J', 'K', // skip `L` @@ -27,12 +25,16 @@ constexpr int8_t SHORT_CODE_TABLE[32] { 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', }; -constexpr int8_t SHORT_CODE_TABLE_REV[42] { - 0, 1, 2, 3, 4, 5, 6, 7, 8, // `1`(49) ~ `9`(57) - -1, -1, -1, -1, -1, -1, -1, // `:`(58) ~ `@`(64) - 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, // `A`(65) ~ `J`(74) - 18, -1, 19, 20, -1, 21, 22, 23, 24, 25, // `K`(75) ~ `T`(84) - 26, 27, 28, 29, 30, 31, // `U`(85) ~ `Z`(90) +constexpr char SHORT_CODE_TABLE_REV[74] { + 0, 1, 2, 3, 4, 5, 6, 7, 8, // `1` ~ `9` | [49, 57] + -1, -1, -1, -1, -1, -1, -1, // | [58, 64] + 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, // `A` ~ `J` | [65, 74] + 18, -1, 19, 20, -1, 21, 22, 23, 24, 25, // `K` ~ `T` | [75, 84] + 26, 27, 28, 29, 30, 31, // `U` ~ `Z` | [85, 90] + -1, -1, -1, -1, -1, -1, // | [91, 96] + 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, // `a` ~ `j` | [97, 106] + 18, -1, 19, 20, -1, 21, 22, 23, 24, 25, // `k` ~ `t` | [107, 116] + 26, 27, 28, 29, 30, 31, // `u` ~ `z` | [117, 122] }; } // namespace klotski::codec diff --git a/src/core/short_code/short_code.h b/src/core/short_code/short_code.h index 9a6d5d8..0f8a366 100644 --- a/src/core/short_code/short_code.h +++ b/src/core/short_code/short_code.h @@ -174,7 +174,7 @@ private: static std::string string_encode(uint32_t short_code); /// Deserialize ShortCode from string and return nullopt on error. - static std::optional string_decode(const std::string &short_code); + static std::optional string_decode(std::string_view short_code); // ------------------------------------------------------------------------------------- // };