Skip to content

Commit

Permalink
[struct_pack] improve performance when deserialize vector<pod>/string (
Browse files Browse the repository at this point in the history
  • Loading branch information
poor-circle authored Nov 27, 2023
1 parent 1d6d03a commit 091ce7c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 12 deletions.
10 changes: 5 additions & 5 deletions include/ylt/struct_pack/unpacker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -995,15 +995,15 @@ class unpacker {
}
else if constexpr (is_little_endian_copyable<sizeof(
value_type)>) {
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<size_type, version, NotSkip>(i);
if SP_UNLIKELY (code != struct_pack::errc{}) {
Expand Down
34 changes: 27 additions & 7 deletions include/ylt/struct_pack/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,15 @@
#include <vector>

#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 <typename T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;

Expand Down Expand Up @@ -134,18 +141,27 @@ template class string_thief<decltype(&std::string::_Mypair),

void string_set_length_hacker(std::string &, std::size_t);

#ifndef __clang__
#define __has_feature(X) false
#endif

template <typename ch>
inline void resize(std::basic_string<ch> &raw_str, std::size_t sz) {
std::string &str = *reinterpret_cast<std::string *>(&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
Expand Down Expand Up @@ -195,20 +211,24 @@ template class vector_thief<decltype(&std::vector<char>::_Mypair),

template <typename ch>
inline void resize(std::vector<ch> &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<char> &vec = *reinterpret_cast<std::vector<char> *>(&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 <typename T>
inline void resize(T &str, std::size_t sz) {
str.resize(sz);
Expand Down

0 comments on commit 091ce7c

Please sign in to comment.