Skip to content

Commit

Permalink
[struct_pack] limit force inline (#254)
Browse files Browse the repository at this point in the history
* [struct_pack] avoid excess optimize in benchmark.

* [struct_pack] Limit force inline when STRUCT_PACK_OPTIMIZE no defined

* fix
  • Loading branch information
poor-circle committed Mar 28, 2023
1 parent 36de71d commit 454802d
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 143 deletions.
2 changes: 1 addition & 1 deletion include/struct_pack/struct_pack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ using unexpected = tl::unexpected<T>;
using unexpect_t = tl::unexpect_t;
#endif

inline std::error_code make_error_code(struct_pack::errc err) {
STRUCT_PACK_INLINE std::error_code make_error_code(struct_pack::errc err) {
return std::error_code(static_cast<int>(err),
struct_pack::detail::category());
}
Expand Down
6 changes: 6 additions & 0 deletions include/struct_pack/struct_pack/reflection.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@
#define CONSTEXPR_INLINE_LAMBDA constexpr __attribute__((always_inline))
#endif

#if defined STRUCT_PACK_OPTIMIZE
#define STRUCT_PACK_MAY_INLINE STRUCT_PACK_INLINE
#else
#define STRUCT_PACK_MAY_INLINE inline
#endif

namespace struct_pack {

template <typename T>
Expand Down
279 changes: 139 additions & 140 deletions include/struct_pack/struct_pack/struct_pack_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1711,9 +1711,9 @@ class packer {

template <serialize_config conf = serialize_config{},
struct_pack::writer_t Writer, typename... Args>
STRUCT_PACK_INLINE void serialize_to(Writer &writer,
const serialize_buffer_size &info,
const Args &...args) {
STRUCT_PACK_MAY_INLINE void serialize_to(Writer &writer,
const serialize_buffer_size &info,
const Args &...args) {
static_assert(sizeof...(args) > 0);
detail::packer<Writer, detail::get_args_type<Args...>> o(writer, info);
switch ((info.metainfo() & 0b11000) >> 3) {
Expand Down Expand Up @@ -1792,139 +1792,8 @@ class unpacker {

STRUCT_PACK_INLINE unpacker(Reader &reader) : reader_(reader) {}

template <typename T, typename... Args, size_t... I>
STRUCT_PACK_INLINE struct_pack::errc deserialize_compatibles(
T &t, Args &...args, std::index_sequence<I...>) {
using Type = get_args_type<T, Args...>;
struct_pack::errc err_code;
switch (size_type_) {
case 0:
([&] {
err_code = deserialize_many<1, compatible_version_number<Type>[I]>(
t, args...);
return err_code == errc::ok;
}() &&
...);
break;
#ifdef STRUCT_PACK_OPTIMIZE
case 1:
([&] {
err_code = deserialize_many<2, compatible_version_number<Type>[I]>(
t, args...);
return err_code == errc::ok;
}() &&
...);
break;
case 2:
([&] {
err_code = deserialize_many<4, compatible_version_number<Type>[I]>(
t, args...);
return err_code == errc::ok;
}() &&
...);
break;
case 3:
([&] {
err_code = deserialize_many<8, compatible_version_number<Type>[I]>(
t, args...);
return err_code == errc::ok;
}() &&
...);
break;
#else
case 1:
case 2:
case 3:
([&] {
err_code = deserialize_many<2, compatible_version_number<Type>[I]>(
t, args...);
return err_code == errc::ok;
}() &&
...);
break;
#endif
default:
unreachable();
}
if (size_type_ ==
UCHAR_MAX) { // reuse size_type_ as a tag that the buffer miss some
// compatible field, whic is legal.
err_code = {};
}
return err_code;
}

template <typename U, size_t I, size_t... Is>
STRUCT_PACK_INLINE struct_pack::errc deserialize_compatible_fields(
std::tuple_element_t<I, decltype(get_types<U>())> &field,
std::index_sequence<Is...>) {
using T = std::remove_cvref_t<U>;
using Type = get_args_type<T>;
struct_pack::errc err_code;
switch (size_type_) {
case 0:
([&] {
err_code =
get_field_impl<1, compatible_version_number<Type>[Is], U, I>(
field);
return err_code == errc::ok;
}() &&
...);
break;
#ifdef STRUCT_PACK_OPTIMIZE
case 1:
([&] {
err_code =
get_field_impl<2, compatible_version_number<Type>[Is], U, I>(
field);
return err_code == errc::ok;
}() &&
...);
break;
case 2:
([&] {
err_code =
get_field_impl<4, compatible_version_number<Type>[Is], U, I>(
field);
return err_code == errc::ok;
}() &&
...);
break;
case 3:
([&] {
err_code =
get_field_impl<8, compatible_version_number<Type>[Is], U, I>(
field);
return err_code == errc::ok;
}() &&
...);
break;
#else
case 1:
case 2:
case 3:
([&] {
err_code =
get_field_impl<2, compatible_version_number<Type>[Is], U, I>(
field);
return err_code == errc::ok;
}() &&
...);
break;
#endif
default:
unreachable();
}
if (size_type_ ==
UCHAR_MAX) { // reuse size_type_ as a tag that the buffer miss some
// compatible field, whic is legal.
err_code = {};
}
return err_code;
}

template <typename T, typename... Args>
STRUCT_PACK_INLINE struct_pack::errc deserialize(T &t, Args &...args) {
STRUCT_PACK_MAY_INLINE struct_pack::errc deserialize(T &t, Args &...args) {
using Type = get_args_type<T, Args...>;
constexpr bool has_compatible =
check_if_compatible_element_exist<decltype(get_types<Type>())>();
Expand Down Expand Up @@ -1974,9 +1843,8 @@ class unpacker {
}

template <typename T, typename... Args>
STRUCT_PACK_INLINE struct_pack::errc deserialize_with_len(std::size_t &len,
T &t,
Args &...args) {
STRUCT_PACK_MAY_INLINE struct_pack::errc deserialize_with_len(
std::size_t &len, T &t, Args &...args) {
using Type = get_args_type<T, Args...>;
constexpr bool has_compatible =
check_if_compatible_element_exist<decltype(get_types<Type>())>();
Expand Down Expand Up @@ -2027,7 +1895,7 @@ class unpacker {
}

template <typename U, size_t I>
STRUCT_PACK_INLINE struct_pack::errc get_field(
STRUCT_PACK_MAY_INLINE struct_pack::errc get_field(
std::tuple_element_t<I, decltype(get_types<U>())> &field) {
using T = std::remove_cvref_t<U>;
using Type = get_args_type<T>;
Expand Down Expand Up @@ -2080,6 +1948,138 @@ class unpacker {
return err_code;
}

private:
template <typename T, typename... Args, size_t... I>
STRUCT_PACK_INLINE struct_pack::errc deserialize_compatibles(
T &t, Args &...args, std::index_sequence<I...>) {
using Type = get_args_type<T, Args...>;
struct_pack::errc err_code;
switch (size_type_) {
case 0:
([&] {
err_code = deserialize_many<1, compatible_version_number<Type>[I]>(
t, args...);
return err_code == errc::ok;
}() &&
...);
break;
#ifdef STRUCT_PACK_OPTIMIZE
case 1:
([&] {
err_code = deserialize_many<2, compatible_version_number<Type>[I]>(
t, args...);
return err_code == errc::ok;
}() &&
...);
break;
case 2:
([&] {
err_code = deserialize_many<4, compatible_version_number<Type>[I]>(
t, args...);
return err_code == errc::ok;
}() &&
...);
break;
case 3:
([&] {
err_code = deserialize_many<8, compatible_version_number<Type>[I]>(
t, args...);
return err_code == errc::ok;
}() &&
...);
break;
#else
case 1:
case 2:
case 3:
([&] {
err_code = deserialize_many<2, compatible_version_number<Type>[I]>(
t, args...);
return err_code == errc::ok;
}() &&
...);
break;
#endif
default:
unreachable();
}
if (size_type_ ==
UCHAR_MAX) { // reuse size_type_ as a tag that the buffer miss some
// compatible field, whic is legal.
err_code = {};
}
return err_code;
}

template <typename U, size_t I, size_t... Is>
STRUCT_PACK_INLINE struct_pack::errc deserialize_compatible_fields(
std::tuple_element_t<I, decltype(get_types<U>())> &field,
std::index_sequence<Is...>) {
using T = std::remove_cvref_t<U>;
using Type = get_args_type<T>;
struct_pack::errc err_code;
switch (size_type_) {
case 0:
([&] {
err_code =
get_field_impl<1, compatible_version_number<Type>[Is], U, I>(
field);
return err_code == errc::ok;
}() &&
...);
break;
#ifdef STRUCT_PACK_OPTIMIZE
case 1:
([&] {
err_code =
get_field_impl<2, compatible_version_number<Type>[Is], U, I>(
field);
return err_code == errc::ok;
}() &&
...);
break;
case 2:
([&] {
err_code =
get_field_impl<4, compatible_version_number<Type>[Is], U, I>(
field);
return err_code == errc::ok;
}() &&
...);
break;
case 3:
([&] {
err_code =
get_field_impl<8, compatible_version_number<Type>[Is], U, I>(
field);
return err_code == errc::ok;
}() &&
...);
break;
#else
case 1:
case 2:
case 3:
([&] {
err_code =
get_field_impl<2, compatible_version_number<Type>[Is], U, I>(
field);
return err_code == errc::ok;
}() &&
...);
break;
#endif
default:
unreachable();
}
if (size_type_ ==
UCHAR_MAX) { // reuse size_type_ as a tag that the buffer miss some
// compatible field, whic is legal.
err_code = {};
}
return err_code;
}

template <std::size_t size_type, uint64_t version, typename U, size_t I>
STRUCT_PACK_INLINE struct_pack::errc get_field_impl(
std::tuple_element_t<I, decltype(get_types<U>())> &field) {
Expand Down Expand Up @@ -2108,7 +2108,6 @@ class unpacker {
return err_code;
}

private:
template <size_t index, typename size_type, typename version,
typename NotSkip>
struct variant_construct_helper {
Expand Down
2 changes: 2 additions & 0 deletions src/struct_pack/benchmark/msgpack_sample.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct message_pack_sample : public base_sample {
for (int i = 0; i < ITERATIONS; ++i) {
buffer_.clear();
msgpack::pack(buffer_, sample);
no_op(buffer_.data());
}
}
ser_time_elapsed_map_.emplace(sample_type, ns);
Expand Down Expand Up @@ -86,6 +87,7 @@ struct message_pack_sample : public base_sample {
msgpack::unpack(vec[i], buffer_.data(), buffer_.size());
vec[i].get().as<T>();
}
no_op((char *)vec.data());
}
deser_time_elapsed_map_.emplace(sample_type, ns);
}
Expand Down
4 changes: 3 additions & 1 deletion src/struct_pack/benchmark/no_op.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "no_op.h"

void no_op(std::vector<Monster>* monsters) {}
void no_op(std::string& str) {}

void no_op(char* data) {}
3 changes: 2 additions & 1 deletion src/struct_pack/benchmark/no_op.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include "data_def.hpp"

void no_op(std::vector<Monster>* monsters = nullptr);
void no_op(std::string& str);
void no_op(char* data);
Loading

0 comments on commit 454802d

Please sign in to comment.