Skip to content

Commit 5d7790a

Browse files
author
pfeatherstone
committed
- bulk write format and value
- bench against msgpack_c
1 parent 1e4d6f1 commit 5d7790a

File tree

3 files changed

+156
-85
lines changed

3 files changed

+156
-85
lines changed

bench/CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@ FetchContent_Declare(
1515
URL_HASH MD5=537da0e22b31b8b7185cc44fdde70458
1616
DOWNLOAD_EXTRACT_TIMESTAMP true
1717
)
18-
FetchContent_MakeAvailable(Boost)
18+
set(MSGPACK_USE_BOOST OFF CACHE INTERNAL "Disabling boost in msgpack library")
19+
FetchContent_Declare(
20+
msgpack
21+
GIT_REPOSITORY https://github.com/msgpack/msgpack-c.git
22+
GIT_TAG cpp_master
23+
)
24+
FetchContent_MakeAvailable(Boost msgpack)
1925

2026
# Examples
2127
add_executable(Bench main.cpp)
2228
target_include_directories(Bench PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include)
2329
target_compile_features(Bench PRIVATE cxx_std_17)
2430
target_compile_options(Bench PRIVATE $<${IS_NOT_MSVC}:-Wall -Wextra -Werror>)
2531
target_link_options(Bench PRIVATE $<$<AND:$<CONFIG:RELEASE>,${IS_NOT_MSVC}>:-s>)
26-
target_link_libraries(Bench PRIVATE Boost::describe)
32+
target_link_libraries(Bench PRIVATE Boost::describe msgpack-cxx)

bench/main.cpp

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <chrono>
22
#include <random>
33
#include <boost/describe/class.hpp>
4+
#include <msgpack.hpp>
45
#define ANKERL_NANOBENCH_IMPLEMENT
56
#include "nanobench.h"
67
#include "msgpack.h"
@@ -41,6 +42,40 @@ std::string make_string()
4142
"importance.";
4243
}
4344

45+
template<class Byte, class Allocator>
46+
struct vector_sink
47+
{
48+
std::vector<Byte, Allocator>& buf;
49+
vector_sink(std::vector<Byte, Allocator>& buf_) : buf{buf_} {}
50+
void write(const char* data, size_t len) {buf.insert(end(buf), data, data + len);}
51+
};
52+
53+
template <
54+
class T,
55+
class D1 = boost::describe::describe_members<T, boost::describe::mod_any_access>
56+
>
57+
void serialize_msgpack_cxx(std::vector<uint8_t>& buf, const T& obj, bool as_map = false)
58+
{
59+
vector_sink out{buf};
60+
msgpack::packer pack{&out};
61+
62+
if (as_map)
63+
{
64+
pack.pack_map(boost::mp11::mp_size<D1>::value);
65+
boost::mp11::mp_for_each<D1>([&](auto D) {
66+
pack.pack(D.name);
67+
pack.pack(obj.*D.pointer);
68+
});
69+
}
70+
else
71+
{
72+
pack.pack_array(boost::mp11::mp_size<D1>::value);
73+
boost::mp11::mp_for_each<D1>([&](auto D) {
74+
pack.pack(obj.*D.pointer);
75+
});
76+
}
77+
}
78+
4479
namespace custom_namespace
4580
{
4681
struct custom_struct
@@ -63,6 +98,15 @@ namespace custom_namespace
6398
c, i8, u8, i16, u16, i32, u32, i64, u64, f32, f64,
6499
str
65100
))
101+
102+
struct custom_struct2
103+
{
104+
std::vector<custom_struct> array;
105+
std::map<int, custom_struct> map;
106+
std::vector<uint8_t> binary;
107+
};
108+
109+
BOOST_DESCRIBE_STRUCT(custom_struct2, (), (array, map, binary))
66110
}
67111

68112
int main()
@@ -82,11 +126,26 @@ int main()
82126
data.f32 = random<float>(eng);
83127
data.f64 = random<double>(eng);
84128
data.str = make_string();
85-
std::vector<uint8_t> buf;
86129

87-
ankerl::nanobench::Bench().minEpochTime(100ms).maxEpochTime(1s).run("serialize", [&] {
88-
auto out = sink(buf);
130+
// Warmup
131+
std::vector<uint8_t> buf0;
132+
auto out = sink(buf0);
133+
serialize(out, data);
134+
135+
std::vector<uint8_t> buf1;
136+
serialize_msgpack_cxx(buf1, data);
137+
printf("buf0.size() %zu buf1.size() %zu\n", buf0.size(), buf1.size());
138+
139+
ankerl::nanobench::Bench().minEpochTime(100ms).epochs(50).run("msgpackcpp::serialize", [&] {
140+
buf0.clear();
141+
auto out = sink(buf0);
89142
serialize(out, data);
90143
// ankerl::nanobench::doNotOptimizeAway(d);
91144
});
145+
146+
ankerl::nanobench::Bench().minEpochTime(100ms).epochs(50).run("msgpack_c::serialize", [&] {
147+
buf1.clear();
148+
serialize_msgpack_cxx(buf1, data);
149+
// ankerl::nanobench::doNotOptimizeAway(d);
150+
});
92151
}

include/msgpack.h

Lines changed: 86 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,12 @@ namespace msgpackcpp
550550
return format;
551551
}
552552

553+
template<class T>
554+
void store(char* buf, const T& obj)
555+
{
556+
std::memcpy(buf, &obj, sizeof(obj));
557+
}
558+
553559
//----------------------------------------------------------------------------------------------------------------
554560

555561
template<SINK_TYPE Sink>
@@ -603,34 +609,34 @@ namespace msgpackcpp
603609
else if (v <= std::numeric_limits<uint8_t>::max())
604610
{
605611
// unsigned 8
606-
constexpr uint8_t format = MSGPACK_U8;
607-
const uint8_t v8 = static_cast<uint8_t>(v);
608-
out((const char*)&format, 1);
609-
out((const char*)&v8, 1);
612+
char buf[2];
613+
buf[0] = MSGPACK_U8;
614+
buf[1] = static_cast<uint8_t>(v);
615+
out(buf, sizeof(buf));
610616
}
611617
else if (v <= std::numeric_limits<uint16_t>::max())
612618
{
613619
// unsigned 16
614-
constexpr uint8_t format = MSGPACK_U16;
615-
const uint16_t v16 = host_to_b16(static_cast<uint16_t>(v));
616-
out((const char*)&format, 1);
617-
out((const char*)&v16, 2);
620+
char buf[3];
621+
buf[0] = MSGPACK_U16;
622+
store(&buf[1], host_to_b16(static_cast<uint16_t>(v)));
623+
out(buf, sizeof(buf));
618624
}
619625
else if (v <= std::numeric_limits<uint32_t>::max())
620626
{
621627
// unsigned 32
622-
constexpr uint8_t format = MSGPACK_U32;
623-
const uint32_t v32 = host_to_b32(static_cast<uint32_t>(v));
624-
out((const char*)&format, 1);
625-
out((const char*)&v32, 4);
628+
char buf[5];
629+
buf[0] = MSGPACK_U32;
630+
store(&buf[1], host_to_b32(static_cast<uint32_t>(v)));
631+
out(buf, sizeof(buf));
626632
}
627633
else
628634
{
629635
// unsigned 64
630-
constexpr uint8_t format = MSGPACK_U64;
631-
const uint64_t v64 = host_to_b64(static_cast<uint64_t>(v));
632-
out((const char*)&format, 1);
633-
out((const char*)&v64, 8);
636+
char buf[9];
637+
buf[0] = MSGPACK_U64;
638+
store(&buf[1], host_to_b64(static_cast<uint64_t>(v)));
639+
out(buf, sizeof(buf));
634640
}
635641
}
636642

@@ -652,34 +658,34 @@ namespace msgpackcpp
652658
else if (v >= std::numeric_limits<int8_t>::min())
653659
{
654660
// negative - int8
655-
constexpr uint8_t format = MSGPACK_I8;
656-
const int8_t v8 = static_cast<int8_t>(v);
657-
out((const char*)&format, 1);
658-
out((const char*)&v8, 1);
661+
char buf[2];
662+
buf[0] = MSGPACK_I8;
663+
buf[1] = static_cast<int8_t>(v);
664+
out(buf, sizeof(buf));
659665
}
660666
else if (v >= std::numeric_limits<int16_t>::min())
661667
{
662668
// negative - int16
663-
constexpr uint8_t format = MSGPACK_I16;
664-
const uint16_t v16 = host_to_b16(bit_cast<uint16_t>(static_cast<int16_t>(v)));
665-
out((const char*)&format, 1);
666-
out((const char*)&v16, 2);
669+
char buf[3];
670+
buf[0] = MSGPACK_I16;
671+
store(&buf[1], host_to_b16(bit_cast<uint16_t>(static_cast<int16_t>(v))));
672+
out(buf, sizeof(buf));
667673
}
668674
else if (v >= std::numeric_limits<int32_t>::min())
669675
{
670676
// negative - int32_t
671-
constexpr uint8_t format = MSGPACK_I32;
672-
const uint32_t v32 = host_to_b32(bit_cast<uint32_t>(static_cast<int32_t>(v)));
673-
out((const char*)&format, 1);
674-
out((const char*)&v32, 4);
677+
char buf[5];
678+
buf[0] = MSGPACK_I32;
679+
store(&buf[1], host_to_b32(bit_cast<uint32_t>(static_cast<int32_t>(v))));
680+
out(buf, sizeof(buf));
675681
}
676682
else
677683
{
678684
// negative - int64_t
679-
constexpr uint8_t format = MSGPACK_I64;
680-
const uint64_t v64 = host_to_b64(bit_cast<uint64_t>(static_cast<int64_t>(v)));
681-
out((const char*)&format, 1);
682-
out((const char*)&v64, 8);
685+
char buf[9];
686+
buf[0] = MSGPACK_I64;
687+
store(&buf[1], host_to_b64(bit_cast<uint64_t>(static_cast<int64_t>(v))));
688+
out(buf, sizeof(buf));
683689
}
684690
}
685691

@@ -767,19 +773,19 @@ namespace msgpackcpp
767773
template<SINK_TYPE Sink>
768774
inline void serialize(Sink& out, float v)
769775
{
770-
constexpr uint8_t format = MSGPACK_F32;
771-
const uint32_t tmp = host_to_b32(bit_cast<uint32_t>(v));
772-
out((const char*)&format, 1);
773-
out((const char*)&tmp, 4);
776+
char buf[5];
777+
buf[0] = MSGPACK_F32;
778+
store(&buf[1], host_to_b32(bit_cast<uint32_t>(v)));
779+
out(buf, sizeof(buf));
774780
}
775781

776782
template<SINK_TYPE Sink>
777783
inline void serialize(Sink& out, double v)
778784
{
779-
constexpr uint8_t format = MSGPACK_F64;
780-
const uint64_t tmp = host_to_b64(bit_cast<uint64_t>(v));
781-
out((const char*)&format, 1);
782-
out((const char*)&tmp, 8);
785+
char buf[9];
786+
buf[0] = MSGPACK_F64;
787+
store(&buf[1], host_to_b64(bit_cast<uint64_t>(v)));
788+
out(buf, sizeof(buf));
783789
}
784790

785791
template<SOURCE_TYPE Source, class Float, check_float<Float> = true>
@@ -819,24 +825,24 @@ namespace msgpackcpp
819825
}
820826
else if (size < 256)
821827
{
822-
constexpr uint8_t format = MSGPACK_STR8;
823-
const uint8_t size8 = static_cast<uint8_t>(size);
824-
out((const char*)&format, 1);
825-
out((const char*)&size8, 1);
828+
char buf[2];
829+
buf[0] = MSGPACK_STR8;
830+
buf[1] = static_cast<uint8_t>(size);
831+
out(buf, sizeof(buf));
826832
}
827833
else if (size < 65536)
828834
{
829-
constexpr uint8_t format = MSGPACK_STR16;
830-
const uint16_t size16 = host_to_b16(static_cast<uint16_t>(size));
831-
out((const char*)&format, 1);
832-
out((const char*)&size16, 2);
835+
char buf[3];
836+
buf[0] = MSGPACK_STR16;
837+
store(&buf[1], host_to_b16(static_cast<uint16_t>(size)));
838+
out(buf, sizeof(buf));
833839
}
834840
else
835841
{
836-
constexpr uint8_t format = MSGPACK_STR32;
837-
const uint32_t size32 = host_to_b32(static_cast<uint32_t>(size));
838-
out((const char*)&format, 1);
839-
out((const char*)&size32, 4);
842+
char buf[5];
843+
buf[0] = MSGPACK_STR32;
844+
store(&buf[1], host_to_b32(static_cast<uint32_t>(size)));
845+
out(buf, sizeof(buf));
840846
}
841847
}
842848

@@ -910,24 +916,24 @@ namespace msgpackcpp
910916
{
911917
if (len < 256)
912918
{
913-
constexpr uint8_t format = MSGPACK_BIN8;
914-
const uint8_t size8 = static_cast<uint8_t>(len);
915-
out((const char*)&format, 1);
916-
out((const char*)&size8, 1);
919+
char buf[2];
920+
buf[0] = MSGPACK_BIN8;
921+
buf[1] = static_cast<uint8_t>(len);
922+
out(buf, sizeof(buf));
917923
}
918924
else if (len < 65536)
919925
{
920-
constexpr uint8_t format = MSGPACK_BIN16;
921-
const uint16_t size16 = host_to_b16(static_cast<uint16_t>(len));
922-
out((const char*)&format, 1);
923-
out((const char*)&size16, 2);
926+
char buf[3];
927+
buf[0] = MSGPACK_BIN16;
928+
store(&buf[1], host_to_b16(static_cast<uint16_t>(len)));
929+
out(buf, sizeof(buf));
924930
}
925931
else
926932
{
927-
constexpr uint8_t format = MSGPACK_BIN32;
928-
const uint32_t size32 = host_to_b32(static_cast<uint32_t>(len));
929-
out((const char*)&format, 1);
930-
out((const char*)&size32, 4);
933+
char buf[5];
934+
buf[0] = MSGPACK_BIN32;
935+
store(&buf[1], host_to_b32(static_cast<uint32_t>(len)));
936+
out(buf, sizeof(buf));
931937
}
932938
}
933939

@@ -1018,17 +1024,17 @@ namespace msgpackcpp
10181024
}
10191025
else if (size < 65536)
10201026
{
1021-
constexpr uint8_t format = MSGPACK_ARR16;
1022-
const uint16_t size16 = host_to_b16(static_cast<uint16_t>(size));
1023-
out((const char*)&format, 1);
1024-
out((const char*)&size16, 2);
1027+
char buf[3];
1028+
buf[0] = MSGPACK_ARR16;
1029+
store(&buf[1], host_to_b16(static_cast<uint16_t>(size)));
1030+
out(buf, sizeof(buf));
10251031
}
10261032
else
10271033
{
1028-
constexpr uint8_t format = MSGPACK_ARR32;
1029-
const uint32_t size32 = host_to_b32(static_cast<uint32_t>(size));
1030-
out((const char*)&format, 1);
1031-
out((const char*)&size32, 4);
1034+
char buf[5];
1035+
buf[0] = MSGPACK_ARR32;
1036+
store(&buf[1], host_to_b32(static_cast<uint32_t>(size)));
1037+
out(buf, sizeof(buf));
10321038
}
10331039
}
10341040

@@ -1110,17 +1116,17 @@ namespace msgpackcpp
11101116
}
11111117
else if (size < 65536)
11121118
{
1113-
constexpr uint8_t format = MSGPACK_MAP16;
1114-
const uint16_t size16 = host_to_b16(static_cast<uint16_t>(size));
1115-
out((const char*)&format, 1);
1116-
out((const char*)&size16, 2);
1119+
char buf[3];
1120+
buf[0] = MSGPACK_MAP16;
1121+
store(&buf[1], host_to_b16(static_cast<uint16_t>(size)));
1122+
out(buf, sizeof(buf));
11171123
}
11181124
else
11191125
{
1120-
constexpr uint8_t format = MSGPACK_MAP32;
1121-
const uint32_t size32 = host_to_b32(static_cast<uint32_t>(size));
1122-
out((const char*)&format, 1);
1123-
out((const char*)&size32, 4);
1126+
char buf[5];
1127+
buf[0] = MSGPACK_MAP32;
1128+
store(&buf[1], host_to_b32(static_cast<uint32_t>(size)));
1129+
out(buf, sizeof(buf));
11241130
}
11251131
}
11261132

0 commit comments

Comments
 (0)