From fb63e1fe5c2683d004bd4f204ef8baffd60b7749 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Mon, 27 Nov 2023 16:03:21 +0800 Subject: [PATCH] [struct_pack] improve performance when deserialize vector/string --- include/ylt/struct_pack/unpacker.hpp | 10 ++++---- include/ylt/struct_pack/util.h | 34 ++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/include/ylt/struct_pack/unpacker.hpp b/include/ylt/struct_pack/unpacker.hpp index 112655af5..786c655c8 100644 --- a/include/ylt/struct_pack/unpacker.hpp +++ b/include/ylt/struct_pack/unpacker.hpp @@ -995,15 +995,15 @@ class unpacker { } else if constexpr (is_little_endian_copyable) { - item.resize(size64); - if SP_UNLIKELY (!read_bytes_array( - reader_, (char *)item.data(), - size64 * sizeof(value_type))) { + resize(item, size64); + // item.resize(size64); + if SP_UNLIKELY (!read_bytes_array(reader_, (char *)item.data(), + mem_sz)) { return struct_pack::errc::no_buffer_space; } } else { - item.resize(size64); + resize(item, size64); for (auto &i : item) { code = deserialize_one(i); if SP_UNLIKELY (code != struct_pack::errc{}) { diff --git a/include/ylt/struct_pack/util.h b/include/ylt/struct_pack/util.h index 988899928..87d86321e 100644 --- a/include/ylt/struct_pack/util.h +++ b/include/ylt/struct_pack/util.h @@ -21,8 +21,15 @@ #include #include "marco.h" + namespace struct_pack::detail { +#if __cpp_concepts >= 201907L +constexpr bool is_string_reserve_shrink = requires { std::string{}.reserve(); }; +#else +constexpr bool is_string_reserve_shrink = true; +#endif + template using remove_cvref_t = std::remove_cv_t>; @@ -134,18 +141,27 @@ template class string_thief inline void resize(std::basic_string &raw_str, std::size_t sz) { std::string &str = *reinterpret_cast(&raw_str); -#if defined(__SANITIZE_ADDRESS__) +#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) raw_str.resize(sz); #elif defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) || \ defined(_MSVC_STL_VERSION) - if (sz > str.capacity()) { - str.reserve(sz); + if constexpr (is_string_reserve_shrink) { + if (sz > raw_str.capacity()) { + str.reserve(sz * sizeof(ch)); + } + } + else { + str.reserve(sz * sizeof(ch)); } string_set_length_hacker(str, sz); - str[sz] = '\0'; + for (auto i = sz; i < sz + sizeof(ch); ++i) str[i] = '\0'; #else raw_str.resize(sz); #endif @@ -195,20 +211,24 @@ template class vector_thief::_Mypair), template inline void resize(std::vector &raw_vec, std::size_t sz) { -#if defined(__SANITIZE_ADDRESS__) +#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) raw_vec.resize(sz); #elif defined(__GLIBCXX__) || \ (defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_ASAN)) || \ defined(_MSVC_STL_VERSION) std::vector &vec = *reinterpret_cast *>(&raw_vec); - vec.reserve(sz); - vector_set_length_hacker(vec, sz); + vec.reserve(sz * sizeof(ch)); + vector_set_length_hacker(vec, sz * sizeof(ch)); #else raw_vec.resize(sz); #endif } #endif +#ifndef __clang__ +#undef __has_feature +#endif + template inline void resize(T &str, std::size_t sz) { str.resize(sz);