├── .clang-format ├── .gitignore ├── CMakeLists.txt ├── README.md ├── avro └── record.hpp ├── benchmark.cpp ├── boost ├── record.cpp └── record.hpp ├── capnproto ├── test.capnp.c++ └── test.capnp.h ├── cereal ├── record.cpp └── record.hpp ├── data.hpp ├── flatbuffers └── test_generated.h ├── images ├── graphs.R ├── size.png ├── time.png └── time2.png ├── msgpack └── record.hpp ├── protobuf ├── test.pb.cc └── test.pb.h ├── test.capnp ├── test.fbs ├── test.json ├── test.proto ├── test.thrift ├── thrift └── gen-cpp │ ├── test_constants.cpp │ ├── test_constants.h │ ├── test_types.cpp │ └── test_types.h └── yas ├── record.cpp └── record.hpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: WebKit 4 | 5 | BreakBeforeBraces: Linux 6 | ColumnLimit: 120 7 | IndentWidth: 4 8 | Standard: Cpp11 9 | AllowShortBlocksOnASingleLine: false 10 | AllowShortFunctionsOnASingleLine: false 11 | AlwaysBreakTemplateDeclarations: true 12 | AlwaysBreakAfterReturnType: TopLevelDefinitions 13 | BinPackParameters: false 14 | SortIncludes: false 15 | Cpp11BracedListStyle: true 16 | 17 | --- 18 | Language: Proto 19 | DisableFormat: true 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sublime* 2 | *.swp* 3 | .ycm_extra_conf.* 4 | compile_commands.json 5 | build/ 6 | .vscode/ 7 | .clangd/ 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0 FATAL_ERROR) 2 | project(cpp_serializers LANGUAGES CXX VERSION 0.1.0) 3 | 4 | if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8) 5 | message(FATAL_ERROR "Doesn't support non 64-bit platforms") 6 | endif() 7 | 8 | include(FindThreads) 9 | include(CheckTypeSize) 10 | include(CheckIncludeFiles) 11 | include(CheckCXXCompilerFlag) 12 | include(ExternalProject) 13 | 14 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 15 | 16 | CHECK_CXX_COMPILER_FLAG("-std=c++14" CXX14) 17 | if (NOT CXX14) 18 | message(FATAL_ERROR "C++ compiler doesn't support C++14") 19 | endif() 20 | 21 | CHECK_INCLUDE_FILES("inttypes.h" HAVE_INTTYPES_H) 22 | CHECK_INCLUDE_FILES("netinet/in.h" HAVE_NETINET_IN_H) 23 | 24 | if (HAVE_INTTYPES_H) 25 | add_definitions("-DHAVE_INTTYPES_H") 26 | endif() 27 | 28 | if (HAVE_NETINET_IN_H) 29 | add_definitions("-DHAVE_NETINET_IN_H") 30 | endif() 31 | 32 | include_directories(${cpp_serializers_SOURCE_DIR}) 33 | 34 | find_package(ZLIB) 35 | if (NOT ZLIB_FOUND) 36 | message(FATAL_ERROR "Couldn't find zlib library") 37 | endif() 38 | include_directories(${ZLIB_INCLUDE_DIRS}) 39 | 40 | find_program(AUTORECONF NAMES autoreconf) 41 | if (NOT AUTORECONF) 42 | message(FATAL_ERROR "Autoreconf not found") 43 | else() 44 | message(STATUS "Found autoreconf: ${AUTORECONF}") 45 | endif() 46 | 47 | find_program(LIBTOOL NAMES libtool libtoolize) 48 | if (NOT LIBTOOL) 49 | message(FATAL_ERROR "Libtool not found") 50 | else() 51 | message(STATUS "Found libtool: ${LIBTOOL}") 52 | endif() 53 | 54 | set(CXXOPTS_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/cxxopts) 55 | ExternalProject_Add( 56 | cxxopts 57 | PREFIX ${CXXOPTS_PREFIX} 58 | URL "https://github.com/jarro2783/cxxopts/archive/v2.1.2.tar.gz" 59 | URL_MD5 "51af98ad0b7ec6fb7aa1cf96ea65fff8" 60 | CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${CXXOPTS_PREFIX} 61 | LOG_UPDATE ON 62 | LOG_BUILD ON 63 | LOG_INSTALL ON 64 | ) 65 | 66 | set(boost_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/boost) 67 | ExternalProject_Add( 68 | boost 69 | PREFIX ${boost_PREFIX} 70 | URL "http://netcologne.dl.sourceforge.net/project/boost/boost/1.69.0/boost_1_69_0.tar.gz" 71 | URL_MD5 "b50944c0c13f81ce2c006802a1186f5a" 72 | CONFIGURE_COMMAND ${boost_PREFIX}/src/boost/bootstrap.sh --with-libraries=serialization,filesystem,system,program_options,iostreams --prefix=${boost_PREFIX} 73 | BUILD_COMMAND ./bjam link=static cxxflags='-fPIC' 74 | INSTALL_COMMAND ./bjam link=static install 75 | BUILD_IN_SOURCE 1 76 | LOG_UPDATE ON 77 | LOG_CONFIGURE ON 78 | LOG_BUILD ON 79 | LOG_INSTALL ON 80 | ) 81 | set(Boost_INCLUDE_DIRS ${boost_PREFIX}) 82 | set(BOOST_LIBRARIES ${boost_PREFIX}/lib/libboost_serialization.a) 83 | message(STATUS "Using Boost from ${Boost_INCLUDE_DIRS}/include") 84 | 85 | set(thrift_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/thrift) 86 | ExternalProject_Add( 87 | thrift 88 | PREFIX ${thrift_PREFIX} 89 | DEPENDS boost 90 | URL "http://www-eu.apache.org/dist/thrift/0.12.0/thrift-0.12.0.tar.gz" 91 | URL_MD5 "3deebbb4d1ca77dd9c9e009a1ea02183" 92 | CONFIGURE_COMMAND CXX=${CMAKE_CXX_COMPILER} CC=${CMAKE_C_COMPILER} ${thrift_PREFIX}/src/thrift/configure --prefix=${thrift_PREFIX} --libdir=${thrift_PREFIX}/lib --with-boost=${Boost_INCLUDE_DIRS} --enable-shared=no --with-libevent=no --with-c_glib=no --with-java=no --with-erlang=no --with-python=no --with-perl=no --with-php=no --with-php_extension=no --with-ruby=no --with-haskell=no --with-go=no --with-d=no --with-lua=no --with-qt4=no --with-qt5=no --with-nodejs=no --with-cl=no --with-dotnetcore=no --with-nodets=no --with-rs=no --disable-tests --enable-plugin=no 93 | BUILD_COMMAND $(MAKE) 94 | INSTALL_COMMAND $(MAKE) install 95 | BUILD_IN_SOURCE 1 96 | LOG_UPDATE ON 97 | LOG_BUILD ON 98 | LOG_INSTALL ON 99 | ) 100 | set(THRIFT_LIBRARIES ${thrift_PREFIX}/lib/libthrift.a) 101 | set(THRIFT_GENERATOR ${thrift_PREFIX}/bin/thrift) 102 | 103 | set(msgpack_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/msgpack) 104 | ExternalProject_Add( 105 | msgpack 106 | PREFIX ${msgpack_PREFIX} 107 | URL "https://github.com/msgpack/msgpack-c/releases/download/cpp-3.1.1/msgpack-3.1.1.tar.gz" 108 | URL_MD5 "99ddfbc004576d5b5261a7f0e68962e7" 109 | CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${msgpack_PREFIX} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} 110 | BUILD_IN_SOURCE 1 111 | LOG_UPDATE ON 112 | LOG_BUILD ON 113 | LOG_INSTALL ON 114 | ) 115 | set(MSGPACK_LIBRARIES ${msgpack_PREFIX}/lib/libmsgpackc.a) 116 | 117 | set(protobuf_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/protobuf) 118 | ExternalProject_Add( 119 | protobuf 120 | PREFIX ${protobuf_PREFIX} 121 | URL "https://github.com/protocolbuffers/protobuf/releases/download/v3.7.0/protobuf-cpp-3.7.0.tar.gz" 122 | URL_MD5 "f1631a8e551e569273d78538f6ecf41c" 123 | CONFIGURE_COMMAND CXX=${CMAKE_CXX_COMPILER} CC=${CMAKE_C_COMPILER} ${protobuf_PREFIX}/src/protobuf/configure --prefix=${protobuf_PREFIX} --libdir=${protobuf_PREFIX}/lib --enable-shared=no 124 | BUILD_COMMAND $(MAKE) 125 | INSTALL_COMMAND $(MAKE) install 126 | BUILD_IN_SOURCE 1 127 | LOG_UPDATE ON 128 | LOG_BUILD ON 129 | LOG_INSTALL ON 130 | ) 131 | set(PROTOBUF_LIBRARIES ${protobuf_PREFIX}/lib/libprotobuf.a) 132 | set(PROTOBUF_GENERATOR ${protobuf_PREFIX}/bin/protoc) 133 | 134 | set(capnproto_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/capnproto) 135 | ExternalProject_Add( 136 | capnproto 137 | PREFIX ${capnproto_PREFIX} 138 | URL "https://github.com/capnproto/capnproto/archive/v0.7.0.tar.gz" 139 | URL_MD5 "a9de5f042f4cf05515c2d7dfc7f5df21" 140 | CONFIGURE_COMMAND CXX=${CMAKE_CXX_COMPILER} CC=${CMAKE_C_COMPILER} cd ${capnproto_PREFIX}/src/capnproto/c++ && ${AUTORECONF} -i && cd - && ${capnproto_PREFIX}/src/capnproto/c++/configure --prefix=${capnproto_PREFIX} --libdir=${capnproto_PREFIX}/lib --enable-shared=no 141 | BUILD_COMMAND $(MAKE) 142 | INSTALL_COMMAND $(MAKE) install 143 | BUILD_IN_SOURCE 1 144 | LOG_UPDATE ON 145 | LOG_BUILD ON 146 | LOG_INSTALL ON 147 | ) 148 | set(CAPNPROTO_LIBRARIES ${capnproto_PREFIX}/lib/libcapnp.a ${capnproto_PREFIX}/lib/libkj.a) 149 | set(CAPNPROTO_GENERATOR ${capnproto_PREFIX}/bin/capnp) 150 | set(CAPNPROTO_CPP_GENERATOR ${capnproto_PREFIX}/bin/capnpc-c++) 151 | 152 | set(cereal_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/cereal) 153 | ExternalProject_Add( 154 | cereal 155 | PREFIX ${cereal_PREFIX} 156 | URL "https://github.com/USCiLab/cereal/archive/v1.2.2.tar.gz" 157 | URL_MD5 "4c56c7b9499dba79404250ef9a040481" 158 | CONFIGURE_COMMAND "" 159 | BUILD_COMMAND "" 160 | INSTALL_COMMAND mkdir -p ${cereal_PREFIX}/include/ && cp -r ${cereal_PREFIX}/src/cereal/include/cereal ${cereal_PREFIX}/include/ 161 | ) 162 | 163 | set(avro_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/avro) 164 | ExternalProject_Add( 165 | avro 166 | DEPENDS boost 167 | PREFIX ${avro_PREFIX} 168 | URL "https://github.com/apache/avro/archive/release-1.8.2.tar.gz" 169 | URL_MD5 "dcaa6eaa0c0854c535b9daf1c024cb35" 170 | CONFIGURE_COMMAND cmake -DBOOST_INCLUDEDIR=${boost_PREFIX}/include -DBOOST_LIBRARYDIR=${boost_PREFIX}/lib -DBoost_NO_SYSTEM_PATHS=ON -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${avro_PREFIX} -DBUILD_SHARED_LIBS=OFF ${avro_PREFIX}/src/avro/lang/c++/ 171 | # Due to some issues with using statically built boost libraries AND zlib in avro tests 172 | # build only necessary parts and install them in a very hackish way. 173 | BUILD_COMMAND $(MAKE) avrocpp_s avrogencpp 174 | INSTALL_COMMAND mkdir -p ${avro_PREFIX}/include/avro ${avro_PREFIX}/lib ${avro_PREFIX}/bin && cp ${avro_PREFIX}/src/avro-build/avrogencpp ${avro_PREFIX}/bin && cp ${avro_PREFIX}/src/avro-build/libavrocpp_s.a ${avro_PREFIX}/lib && cd ${avro_PREFIX}/src/avro/lang/c++/api/ && cp -r . ${avro_PREFIX}/include/avro/ 175 | LOG_UPDATE ON 176 | LOG_CONFIGURE ON 177 | LOG_BUILD ON 178 | ) 179 | set(AVRO_LIBRARIES ${avro_PREFIX}/lib/libavrocpp_s.a) 180 | set(AVRO_GENERATOR ${avro_PREFIX}/bin/avrogencpp) 181 | 182 | set(flatbuffers_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/flatbuffers) 183 | ExternalProject_Add( 184 | flatbuffers 185 | PREFIX ${flatbuffers_PREFIX} 186 | URL "https://github.com/google/flatbuffers/archive/v1.10.0.tar.gz" 187 | URL_MD5 "f7d19a3f021d93422b0bc287d7148cd2" 188 | CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${flatbuffers_PREFIX} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} 189 | LOG_UPDATE ON 190 | LOG_CONFIGURE ON 191 | LOG_BUILD ON 192 | ) 193 | set(FLATBUFFERS_LIBRARIES ${flatbuffers_PREFIX}/lib/libflatbuffers.a) 194 | set(FLATBUFFERS_GENERATOR ${flatbuffers_PREFIX}/bin/flatc) 195 | 196 | set(yas_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/yas) 197 | ExternalProject_Add( 198 | yas 199 | PREFIX ${yas_PREFIX} 200 | URL "https://github.com/niXman/yas/archive/7.0.2.tar.gz" 201 | URL_MD5 "d55353960467afabc6774583880a30f0" 202 | CONFIGURE_COMMAND "" 203 | BUILD_COMMAND "" 204 | INSTALL_COMMAND mkdir -p ${yas_PREFIX}/include/ && cp -r ${yas_PREFIX}/src/yas/include/yas ${yas_PREFIX}/include/ 205 | ) 206 | 207 | set(LINKLIBS 208 | ${THRIFT_LIBRARIES} 209 | ${MSGPACK_LIBRARIES} 210 | ${PROTOBUF_LIBRARIES} 211 | ${CAPNPROTO_LIBRARIES} 212 | ${BOOST_LIBRARIES} 213 | ${AVRO_LIBRARIES} 214 | ${FLATBUFFERS_LIBRARIES} 215 | ${CMAKE_THREAD_LIBS_INIT} 216 | ${ZLIB_LIBRARIES} 217 | ) 218 | 219 | add_custom_command( 220 | DEPENDS ${cpp_serializers_SOURCE_DIR}/test.thrift 221 | COMMAND ${THRIFT_GENERATOR} 222 | ARGS -r -gen cpp -o ${cpp_serializers_SOURCE_DIR}/thrift/ ${cpp_serializers_SOURCE_DIR}/test.thrift 223 | OUTPUT "${cpp_serializers_SOURCE_DIR}/thrift/gen-cpp/test_constants.cpp" 224 | "${cpp_serializers_SOURCE_DIR}/thrift/gen-cpp/test_types.cpp" 225 | COMMENT "Executing Thrift compiler" 226 | ) 227 | set_source_files_properties( 228 | ${cpp_serializers_SOURCE_DIR}/thrift/gen-cpp/test_constants.cpp 229 | ${cpp_serializers_SOURCE_DIR}/thrift/gen-cpp/test_types.cpp 230 | ${cpp_serializers_SOURCE_DIR}/thrift/gen-cpp/test_constants.h 231 | ${cpp_serializers_SOURCE_DIR}/thrift/gen-cpp/test_types.h 232 | PROPERTIES GENERATED TRUE 233 | ) 234 | set(THRIFT_SERIALIZATION_SOURCES ${cpp_serializers_SOURCE_DIR}/thrift/gen-cpp/test_constants.cpp 235 | ${cpp_serializers_SOURCE_DIR}/thrift/gen-cpp/test_types.cpp 236 | ) 237 | 238 | add_custom_command( 239 | DEPENDS ${cpp_serializers_SOURCE_DIR}/test.proto 240 | COMMAND ${PROTOBUF_GENERATOR} 241 | ARGS -I${cpp_serializers_SOURCE_DIR} --cpp_out=${cpp_serializers_SOURCE_DIR}/protobuf ${cpp_serializers_SOURCE_DIR}/test.proto 242 | OUTPUT "${cpp_serializers_SOURCE_DIR}/protobuf/test.pb.cc" 243 | COMMENT "Executing Protobuf compiler" 244 | ) 245 | set_source_files_properties( 246 | ${cpp_serializers_SOURCE_DIR}/protobuf/test.pb.cc 247 | ${cpp_serializers_SOURCE_DIR}/protobuf/test.pb.h 248 | PROPERTIES GENERATED TRUE 249 | ) 250 | set(PROTOBUF_SERIALIZATION_SOURCES ${cpp_serializers_SOURCE_DIR}/protobuf/test.pb.cc) 251 | 252 | add_custom_command( 253 | DEPENDS ${cpp_serializers_SOURCE_DIR}/test.capnp 254 | COMMAND ${CAPNPROTO_GENERATOR} 255 | ARGS compile -I${cpp_serializers_SOURCE_DIR} --src-prefix=${cpp_serializers_SOURCE_DIR} -o${CAPNPROTO_CPP_GENERATOR}:${cpp_serializers_SOURCE_DIR}/capnproto ${cpp_serializers_SOURCE_DIR}/test.capnp 256 | OUTPUT "${cpp_serializers_SOURCE_DIR}/capnproto/test.capnp.c++" 257 | COMMENT "Executing Cap'n Proto compiler" 258 | ) 259 | set_source_files_properties( 260 | ${cpp_serializers_SOURCE_DIR}/capnproto/test.capnp.c++ 261 | ${cpp_serializers_SOURCE_DIR}/capnproto/test.capnp.h 262 | PROPERTIES GENERATED TRUE 263 | ) 264 | set(CAPNPROTO_SERIALIZATION_SOURCES ${cpp_serializers_SOURCE_DIR}/capnproto/test.capnp.c++) 265 | 266 | add_custom_command( 267 | DEPENDS ${cpp_serializers_SOURCE_DIR}/test.json 268 | COMMAND ${AVRO_GENERATOR} 269 | ARGS --input ${cpp_serializers_SOURCE_DIR}/test.json --output ${cpp_serializers_SOURCE_DIR}/avro/record.hpp --namespace avro_test 270 | OUTPUT "${cpp_serializers_SOURCE_DIR}/avro/record.hpp" 271 | COMMENT "Executing Avro compiler" 272 | ) 273 | set_source_files_properties( 274 | ${cpp_serializers_SOURCE_DIR}/avro/record.hpp 275 | PROPERTIES GENERATED TRUE 276 | ) 277 | set(AVRO_SERIALIZATION_SOURCES ${cpp_serializers_SOURCE_DIR}/avro/record.hpp) 278 | 279 | add_custom_command( 280 | DEPENDS ${cpp_serializers_SOURCE_DIR}/test.fbs 281 | COMMAND ${FLATBUFFERS_GENERATOR} 282 | ARGS --cpp -o ${cpp_serializers_SOURCE_DIR}/flatbuffers ${cpp_serializers_SOURCE_DIR}/test.fbs 283 | OUTPUT "${cpp_serializers_SOURCE_DIR}/flatbuffers/test_generated.h" 284 | COMMENT "Executing FlatBuffers compiler" 285 | ) 286 | set_source_files_properties( 287 | ${cpp_serializers_SOURCE_DIR}/flatbuffers/test_generated.h 288 | PROPERTIES GENERATED TRUE 289 | ) 290 | set(FLATBUFFERS_SERIALIZATION_SOURCES ${cpp_serializers_SOURCE_DIR}/flatbuffers/test_generated.h) 291 | 292 | set(BOOST_SERIALIZATION_SOURCES ${cpp_serializers_SOURCE_DIR}/boost/record.cpp) 293 | set(CEREAL_SERIALIZATION_SOURCES ${cpp_serializers_SOURCE_DIR}/cereal/record.cpp) 294 | set(YAS_SERIALIZATION_SOURCES ${cpp_serializers_SOURCE_DIR}/yas/record.cpp) 295 | 296 | add_executable( 297 | benchmark 298 | ${cpp_serializers_SOURCE_DIR}/benchmark.cpp 299 | ${THRIFT_SERIALIZATION_SOURCES} 300 | ${PROTOBUF_SERIALIZATION_SOURCES} 301 | ${CAPNPROTO_SERIALIZATION_SOURCES} 302 | ${BOOST_SERIALIZATION_SOURCES} 303 | ${CEREAL_SERIALIZATION_SOURCES} 304 | ${AVRO_SERIALIZATION_SOURCES} 305 | ${FLATBUFFERS_SERIALIZATION_SOURCES} 306 | ${YAS_SERIALIZATION_SOURCES} 307 | ) 308 | add_dependencies(benchmark cxxopts thrift msgpack protobuf capnproto boost cereal avro flatbuffers yas) 309 | target_link_libraries(benchmark ${LINKLIBS}) 310 | target_include_directories(benchmark SYSTEM PRIVATE ${CXXOPTS_PREFIX}/include) 311 | target_include_directories(benchmark SYSTEM PRIVATE ${thrift_PREFIX}/include) 312 | target_include_directories(benchmark SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}/include) 313 | target_include_directories(benchmark SYSTEM PRIVATE ${avro_PREFIX}/include) 314 | target_include_directories(benchmark SYSTEM PRIVATE ${protobuf_PREFIX}/include) 315 | target_include_directories(benchmark SYSTEM PRIVATE ${yas_PREFIX}/include) 316 | target_include_directories(benchmark SYSTEM PRIVATE ${msgpack_PREFIX}/include) 317 | target_include_directories(benchmark SYSTEM PRIVATE ${capnproto_PREFIX}/include) 318 | target_include_directories(benchmark SYSTEM PRIVATE ${cereal_PREFIX}/include) 319 | target_include_directories(benchmark SYSTEM PRIVATE ${flatbuffers_PREFIX}/include) 320 | target_compile_options(benchmark PRIVATE -W -Wall -Wextra) 321 | set_target_properties(benchmark PROPERTIES 322 | CXX_STANDARD 14 323 | CXX_STANDARD_REQUIRED YES 324 | CXX_EXTENSIONS NO 325 | ) 326 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | Compare various data serialization libraries for C++. 4 | 5 | * [Thrift](http://thrift.apache.org/) 6 | * [Protobuf](https://code.google.com/p/protobuf/) 7 | * [Boost.Serialization](http://www.boost.org/libs/serialization) 8 | * [Msgpack](http://msgpack.org/) 9 | * [Cereal](http://uscilab.github.io/cereal/index.html) 10 | * [Avro](http://avro.apache.org/) 11 | * [Capnproto](https://capnproto.org/) 12 | * [Flatbuffers](https://google.github.io/flatbuffers/) 13 | * [YAS](https://github.com/niXman/yas) 14 | 15 | # Build 16 | 17 | This project does not have any external serialization libraries dependencies. All (boost, thrift etc.) needed libraries are downloaded and built automatically, but you need enough free disk space (approx. 2.3G) to build all components. To build this project you need a compiler that supports C++14 features. Project was tested with Clang and GCC compilers. 18 | 19 | 1. `git clone https://github.com/thekvs/cpp-serializers.git` 20 | 1. `cd cpp-serializers` 21 | 1. `mkdir build` 22 | 1. `cd build` 23 | 1. `cmake -DCMAKE_BUILD_TYPE=Release ..` 24 | 1. `cmake --build .` 25 | 26 | # Usage 27 | 28 | ``` 29 | $ ./benchmark -h 30 | Benchmark various C++ serializers 31 | Usage: 32 | benchmark [OPTION...] 33 | 34 | -h, --help show this help and exit 35 | -l, --list show list of supported serializers 36 | -c, --csv output in CSV format 37 | -i, --iterations arg number of serialize/deserialize iterations 38 | -s, --serializers arg comma separated list of serializers to benchmark 39 | ``` 40 | 41 | * Benchmark **all** serializers, run each serializer 100000 times: 42 | ``` 43 | $ ./benchmark -i 100000 44 | ``` 45 | * Benchmark only **protobuf** serializer, run it 100000 times: 46 | ``` 47 | $ ./benchmark -i 100000 -s protobuf 48 | ``` 49 | * Benchmark **protobuf** and **cereal** serializers only, run each of them 100000 times: 50 | ``` 51 | $ ./benchmark -i 100000 -s protobuf,cereal 52 | ``` 53 | 54 | # Results 55 | 56 | Following results were obtained running 1000000 serialize-deserialize operations 50 times and then averaging results on a typical desktop computer with Intel Core i7 processor running Ubuntu 16.04. Exact versions of libraries used are: 57 | 58 | * thrift 0.12.0 59 | * protobuf 3.7.0 60 | * boost 1.69.0 61 | * msgpack 3.1.1 62 | * cereal 1.2.2 63 | * avro 1.8.2 64 | * capnproto 0.7.0 65 | * flatbuffers 1.10.0 66 | * YAS 7.0.2 67 | 68 | | serializer | object's size | avg. total time | 69 | | -------------- | ------------- | --------------- | 70 | | thrift-binary | 17017 | 1190.22 | 71 | | thrift-compact | 13378 | 3474.32 | 72 | | protobuf | 16116 | 2312.78 | 73 | | boost | 17470 | 1195.04 | 74 | | msgpack | 13402 | 2560.6 | 75 | | cereal | 17416 | 1052.46 | 76 | | avro | 16384 | 4488.18 | 77 | | yas | 17416 | 302.7 | 78 | | yas-compact | 13321 | 2063.34 | 79 | 80 | 81 | ## Size 82 | 83 | ![Size](images/size.png) 84 | 85 | ## Time 86 | 87 | ![Time](images/time.png) 88 | 89 | For capnproto and flatbuffers since they already store data in a "serialized" form and serialization basically means getting pointer to the internal storage, we measure full **build**/serialize/deserialize cycle. In the case of other libraries we measure serialize/deserialize cycle of the already built data structure. 90 | 91 | | serializer | object's size | avg. total time | 92 | | -------------- | ------------- | --------------- | 93 | | capnproto | 17768 | 400.98 | 94 | | flatbuffers | 17632 | 491.5 | 95 | 96 | ![Time](images/time2.png) 97 | 98 | Size measured in bytes, time measured in milliseconds. 99 | -------------------------------------------------------------------------------- /avro/record.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _HOME_PKOK_CPP_SERIALIZERS_AVRO_RECORD_HPP_2710640864__H_ 21 | #define _HOME_PKOK_CPP_SERIALIZERS_AVRO_RECORD_HPP_2710640864__H_ 22 | 23 | 24 | #include 25 | #include "boost/any.hpp" 26 | #include "avro/Specific.hh" 27 | #include "avro/Encoder.hh" 28 | #include "avro/Decoder.hh" 29 | 30 | namespace avro_test { 31 | struct Record { 32 | std::vector ids; 33 | std::vector strings; 34 | Record() : 35 | ids(std::vector()), 36 | strings(std::vector()) 37 | { } 38 | }; 39 | 40 | } 41 | namespace avro { 42 | template<> struct codec_traits { 43 | static void encode(Encoder& e, const avro_test::Record& v) { 44 | avro::encode(e, v.ids); 45 | avro::encode(e, v.strings); 46 | } 47 | static void decode(Decoder& d, avro_test::Record& v) { 48 | if (avro::ResolvingDecoder *rd = 49 | dynamic_cast(&d)) { 50 | const std::vector fo = rd->fieldOrder(); 51 | for (std::vector::const_iterator it = fo.begin(); 52 | it != fo.end(); ++it) { 53 | switch (*it) { 54 | case 0: 55 | avro::decode(d, v.ids); 56 | break; 57 | case 1: 58 | avro::decode(d, v.strings); 59 | break; 60 | default: 61 | break; 62 | } 63 | } 64 | } else { 65 | avro::decode(d, v.ids); 66 | avro::decode(d, v.strings); 67 | } 68 | } 69 | }; 70 | 71 | } 72 | #endif 73 | -------------------------------------------------------------------------------- /benchmark.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "thrift/gen-cpp/test_types.h" 17 | #include "thrift/gen-cpp/test_constants.h" 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include "protobuf/test.pb.h" 25 | #include "capnproto/test.capnp.h" 26 | #include "boost/record.hpp" 27 | #include "msgpack/record.hpp" 28 | #include "cereal/record.hpp" 29 | #include "avro/record.hpp" 30 | #include "flatbuffers/test_generated.h" 31 | #include "yas/record.hpp" 32 | 33 | #include "data.hpp" 34 | 35 | enum class ThriftSerializationProto { Binary, Compact }; 36 | 37 | struct Args { 38 | std::size_t iterations = 0; 39 | std::set serializers; 40 | bool csv = false; 41 | }; 42 | 43 | struct Result { 44 | Result(std::string name, std::string version, size_t size, int64_t time) 45 | : name(name) 46 | , version(version) 47 | , size(size) 48 | , time(time) 49 | { 50 | } 51 | 52 | Result(std::string name, uint64_t version, size_t size, int64_t time) 53 | : name(name) 54 | , version(boost::lexical_cast(version)) 55 | , size(size) 56 | , time(time) 57 | { 58 | } 59 | 60 | std::string name; 61 | std::string version; 62 | size_t size = 0; 63 | int64_t time = 0; 64 | }; 65 | 66 | // clang-format off 67 | const std::set valid_serializers = { 68 | "thrift-binary", 69 | "thrift-compact", 70 | "protobuf", 71 | "boost", 72 | "msgpack", 73 | "cereal", 74 | "avro", 75 | "capnproto", 76 | "flatbuffers", 77 | "yas", 78 | "yas-compact" 79 | }; 80 | // clang-format on 81 | 82 | void 83 | print_results(Args args, std::vector results) 84 | { 85 | if (args.csv) { // print CSV header 86 | std::cout << "serializer,version,iterations,size,time" << std::endl; 87 | } 88 | 89 | for (const auto& result : results) { 90 | if (args.csv) { 91 | std::cout << result.name << "," << result.version << "," << args.iterations << "," << result.size << "," 92 | << result.time << std::endl; 93 | } else { 94 | std::cout << "Serializer: " << result.name << std::endl; 95 | std::cout << "Version : " << result.version << std::endl; 96 | std::cout << "Iterations: " << args.iterations << std::endl; 97 | std::cout << "Size : " << result.size << " bytes" << std::endl; 98 | std::cout << "Time : " << result.time << " milliseconds" << std::endl; 99 | std::cout << std::endl; 100 | } 101 | } 102 | } 103 | 104 | void 105 | print_supported_serializers() 106 | { 107 | std::cerr << std::endl << "Supported serializers are:" << std::endl; 108 | for (const auto& s : valid_serializers) { 109 | std::cout << " * " << s << std::endl; 110 | } 111 | std::cout << std::endl; 112 | } 113 | 114 | Args 115 | parse_args(int argc, char** argv) 116 | { 117 | cxxopts::Options args("benchmark", "Benchmark various C++ serializers"); 118 | 119 | // clang-format off 120 | args.add_options() 121 | ("h,help", "show this help and exit") 122 | ("l,list", "show list of supported serializers") 123 | ("c,csv", "output in CSV format") 124 | ("i,iterations", "number of serialize/deserialize iterations", cxxopts::value()) 125 | ("s,serializers", "comma separated list of serializers to benchmark", cxxopts::value()) 126 | ; 127 | // clang-format on 128 | 129 | Args opts; 130 | 131 | try { 132 | auto parsed_opts = args.parse(argc, argv); 133 | if (parsed_opts.count("help")) { 134 | std::cout << args.help() << std::endl; 135 | exit(EXIT_SUCCESS); 136 | } 137 | 138 | if (parsed_opts.count("list")) { 139 | print_supported_serializers(); 140 | exit(EXIT_SUCCESS); 141 | } 142 | 143 | if (parsed_opts.count("iterations") == 0) { 144 | std::cerr << "Not all required option specified! Please run with -h for available options." << std::endl; 145 | exit(EXIT_FAILURE); 146 | } 147 | 148 | if (parsed_opts.count("serializers")) { 149 | boost::split(opts.serializers, parsed_opts["serializers"].as(), boost::is_any_of(",")); 150 | for (const auto& serializer : opts.serializers) { 151 | auto exists = valid_serializers.find(serializer); 152 | if (exists == valid_serializers.end()) { 153 | std::cerr << "Serializer '" << serializer << "' is not supported by this benchmark." << std::endl; 154 | print_supported_serializers(); 155 | exit(EXIT_FAILURE); 156 | } 157 | } 158 | } 159 | 160 | opts.iterations = parsed_opts["iterations"].as(); 161 | 162 | if (parsed_opts.count("csv")) { 163 | opts.csv = true; 164 | } 165 | } catch (std::exception& exc) { 166 | std::cerr << exc.what() << std::endl; 167 | exit(EXIT_FAILURE); 168 | } 169 | 170 | return opts; 171 | } 172 | 173 | Result 174 | thrift_serialization_test(size_t iterations, ThriftSerializationProto proto = ThriftSerializationProto::Binary) 175 | { 176 | using apache::thrift::protocol::TBinaryProtocol; 177 | using apache::thrift::protocol::TBinaryProtocolT; 178 | using apache::thrift::protocol::TCompactProtocol; 179 | using apache::thrift::protocol::TCompactProtocolT; 180 | using apache::thrift::transport::TMemoryBuffer; 181 | 182 | using namespace thrift_test; 183 | 184 | std::shared_ptr buffer1(new TMemoryBuffer()); 185 | std::shared_ptr buffer2(new TMemoryBuffer()); 186 | 187 | TBinaryProtocolT binary_protocol1(buffer1); 188 | TBinaryProtocolT binary_protocol2(buffer2); 189 | 190 | TCompactProtocolT compact_protocol1(buffer1); 191 | TCompactProtocolT compact_protocol2(buffer2); 192 | 193 | Record r1; 194 | 195 | for (size_t i = 0; i < kIntegers.size(); i++) { 196 | r1.ids.push_back(kIntegers[i]); 197 | } 198 | 199 | for (size_t i = 0; i < kStringsCount; i++) { 200 | r1.strings.push_back(kStringValue); 201 | } 202 | 203 | std::string serialized; 204 | 205 | if (proto == ThriftSerializationProto::Binary) { 206 | r1.write(&binary_protocol1); 207 | } else if (proto == ThriftSerializationProto::Compact) { 208 | r1.write(&compact_protocol1); 209 | } 210 | 211 | serialized = buffer1->getBufferAsString(); 212 | 213 | // check if we can deserialize back 214 | Record r2; 215 | 216 | buffer2->resetBuffer((uint8_t*)serialized.data(), serialized.length()); 217 | 218 | if (proto == ThriftSerializationProto::Binary) { 219 | r2.read(&binary_protocol2); 220 | } else if (proto == ThriftSerializationProto::Compact) { 221 | r2.read(&compact_protocol2); 222 | } 223 | 224 | if (r1 != r2) { 225 | throw std::logic_error("thrift's case: deserialization failed"); 226 | } 227 | 228 | std::string tag; 229 | 230 | if (proto == ThriftSerializationProto::Binary) { 231 | tag = "thrift-binary"; 232 | } else if (proto == ThriftSerializationProto::Compact) { 233 | tag = "thrift-compact"; 234 | } 235 | 236 | auto start = std::chrono::high_resolution_clock::now(); 237 | for (size_t i = 0; i < iterations; i++) { 238 | buffer1->resetBuffer(); 239 | 240 | if (proto == ThriftSerializationProto::Binary) { 241 | r1.write(&binary_protocol1); 242 | } else if (proto == ThriftSerializationProto::Compact) { 243 | r1.write(&compact_protocol1); 244 | } 245 | 246 | serialized = buffer1->getBufferAsString(); 247 | buffer2->resetBuffer((uint8_t*)serialized.data(), serialized.length()); 248 | 249 | if (proto == ThriftSerializationProto::Binary) { 250 | r2.read(&binary_protocol2); 251 | } else if (proto == ThriftSerializationProto::Compact) { 252 | r2.read(&compact_protocol2); 253 | } 254 | } 255 | auto finish = std::chrono::high_resolution_clock::now(); 256 | auto duration = std::chrono::duration_cast(finish - start).count(); 257 | 258 | return Result(tag, PACKAGE_VERSION, serialized.size(), duration); 259 | } 260 | 261 | Result 262 | protobuf_serialization_test(size_t iterations) 263 | { 264 | using namespace protobuf_test; 265 | 266 | Record r1; 267 | 268 | for (size_t i = 0; i < kIntegers.size(); i++) { 269 | r1.add_ids(kIntegers[i]); 270 | } 271 | 272 | for (size_t i = 0; i < kStringsCount; i++) { 273 | r1.add_strings(kStringValue); 274 | } 275 | 276 | std::string serialized; 277 | 278 | r1.SerializeToString(&serialized); 279 | 280 | // check if we can deserialize back 281 | Record r2; 282 | bool ok = r2.ParseFromString(serialized); 283 | if (!ok /*|| r2 != r1*/) { 284 | throw std::logic_error("protobuf's case: deserialization failed"); 285 | } 286 | 287 | auto start = std::chrono::high_resolution_clock::now(); 288 | for (size_t i = 0; i < iterations; i++) { 289 | serialized.clear(); 290 | r1.SerializeToString(&serialized); 291 | r2.ParseFromString(serialized); 292 | } 293 | auto finish = std::chrono::high_resolution_clock::now(); 294 | auto duration = std::chrono::duration_cast(finish - start).count(); 295 | 296 | return Result("protobuf", GOOGLE_PROTOBUF_VERSION, serialized.size(), duration); 297 | } 298 | 299 | Result 300 | capnproto_serialization_test(size_t iterations) 301 | { 302 | using namespace capnp_test; 303 | 304 | capnp::MallocMessageBuilder message; 305 | Record::Builder r1 = message.getRoot(); 306 | 307 | auto ids = r1.initIds(kIntegers.size()); 308 | for (size_t i = 0; i < kIntegers.size(); i++) { 309 | ids.set(i, kIntegers[i]); 310 | } 311 | 312 | auto strings = r1.initStrings(kStringsCount); 313 | for (size_t i = 0; i < kStringsCount; i++) { 314 | strings.set(i, kStringValue); 315 | } 316 | 317 | kj::ArrayPtr> serialized = message.getSegmentsForOutput(); 318 | 319 | // check if we can deserialize back 320 | capnp::SegmentArrayMessageReader reader(serialized); 321 | Record::Reader r2 = reader.getRoot(); 322 | if (r2.getIds().size() != kIntegers.size()) { 323 | throw std::logic_error("capnproto's case: deserialization failed"); 324 | } 325 | 326 | size_t size = 0; 327 | for (auto segment : serialized) { 328 | size += segment.asBytes().size(); 329 | } 330 | 331 | auto start = std::chrono::high_resolution_clock::now(); 332 | for (size_t i = 0; i < iterations; i++) { 333 | capnp::MallocMessageBuilder message; 334 | Record::Builder r1 = message.getRoot(); 335 | 336 | auto ids = r1.initIds(kIntegers.size()); 337 | for (size_t i = 0; i < kIntegers.size(); i++) { 338 | ids.set(i, kIntegers[i]); 339 | } 340 | 341 | auto strings = r1.initStrings(kStringsCount); 342 | for (size_t i = 0; i < kStringsCount; i++) { 343 | strings.set(i, kStringValue); 344 | } 345 | 346 | serialized = message.getSegmentsForOutput(); 347 | capnp::SegmentArrayMessageReader reader(serialized); 348 | auto r2 = reader.getRoot(); 349 | 350 | (void)r2.getIds().size(); 351 | (void)r2.getStrings().size(); 352 | } 353 | auto finish = std::chrono::high_resolution_clock::now(); 354 | auto duration = std::chrono::duration_cast(finish - start).count(); 355 | 356 | return Result("capnproto", CAPNP_VERSION, size, duration); 357 | } 358 | 359 | Result 360 | boost_serialization_test(size_t iterations) 361 | { 362 | using namespace boost_test; 363 | 364 | Record r1, r2; 365 | 366 | for (size_t i = 0; i < kIntegers.size(); i++) { 367 | r1.ids.push_back(kIntegers[i]); 368 | } 369 | 370 | for (size_t i = 0; i < kStringsCount; i++) { 371 | r1.strings.push_back(kStringValue); 372 | } 373 | 374 | std::string serialized; 375 | 376 | to_string(r1, serialized); 377 | from_string(r2, serialized); 378 | 379 | if (r1 != r2) { 380 | throw std::logic_error("boost's case: deserialization failed"); 381 | } 382 | 383 | auto start = std::chrono::high_resolution_clock::now(); 384 | for (size_t i = 0; i < iterations; i++) { 385 | serialized.clear(); 386 | to_string(r1, serialized); 387 | from_string(r2, serialized); 388 | } 389 | auto finish = std::chrono::high_resolution_clock::now(); 390 | auto duration = std::chrono::duration_cast(finish - start).count(); 391 | 392 | return Result("boost", BOOST_VERSION, serialized.size(), duration); 393 | } 394 | 395 | Result 396 | msgpack_serialization_test(size_t iterations) 397 | { 398 | using namespace msgpack_test; 399 | 400 | Record r1, r2; 401 | 402 | for (size_t i = 0; i < kIntegers.size(); i++) { 403 | r1.ids.push_back(kIntegers[i]); 404 | } 405 | 406 | for (size_t i = 0; i < kStringsCount; i++) { 407 | r1.strings.push_back(kStringValue); 408 | } 409 | 410 | msgpack::sbuffer sbuf; 411 | 412 | msgpack::pack(sbuf, r1); 413 | 414 | std::string serialized(sbuf.data(), sbuf.size()); 415 | 416 | msgpack::object_handle msg = msgpack::unpack(serialized.data(), serialized.size()); 417 | 418 | msgpack::object obj = msg.get(); 419 | 420 | obj.convert(r2); 421 | 422 | if (r1 != r2) { 423 | throw std::logic_error("msgpack's case: deserialization failed"); 424 | } 425 | 426 | auto start = std::chrono::high_resolution_clock::now(); 427 | for (size_t i = 0; i < iterations; i++) { 428 | sbuf.clear(); 429 | msgpack::pack(sbuf, r1); 430 | msgpack::object_handle msg = msgpack::unpack(sbuf.data(), sbuf.size()); 431 | msgpack::object obj = msg.get(); 432 | obj.convert(r2); 433 | } 434 | auto finish = std::chrono::high_resolution_clock::now(); 435 | auto duration = std::chrono::duration_cast(finish - start).count(); 436 | 437 | return Result("msgpack", msgpack_version(), serialized.size(), duration); 438 | } 439 | 440 | Result 441 | cereal_serialization_test(size_t iterations) 442 | { 443 | using namespace cereal_test; 444 | 445 | Record r1, r2; 446 | 447 | for (size_t i = 0; i < kIntegers.size(); i++) { 448 | r1.ids.push_back(kIntegers[i]); 449 | } 450 | 451 | for (size_t i = 0; i < kStringsCount; i++) { 452 | r1.strings.push_back(kStringValue); 453 | } 454 | 455 | std::string serialized; 456 | 457 | to_string(r1, serialized); 458 | from_string(r2, serialized); 459 | 460 | if (r1 != r2) { 461 | throw std::logic_error("cereal's case: deserialization failed"); 462 | } 463 | 464 | auto start = std::chrono::high_resolution_clock::now(); 465 | for (size_t i = 0; i < iterations; i++) { 466 | serialized.clear(); 467 | to_string(r1, serialized); 468 | from_string(r2, serialized); 469 | } 470 | auto finish = std::chrono::high_resolution_clock::now(); 471 | auto duration = std::chrono::duration_cast(finish - start).count(); 472 | 473 | return Result("cereal", "", serialized.size(), duration); 474 | } 475 | 476 | Result 477 | avro_serialization_test(size_t iterations) 478 | { 479 | using namespace avro_test; 480 | 481 | Record r1, r2; 482 | 483 | for (size_t i = 0; i < kIntegers.size(); i++) { 484 | r1.ids.push_back(kIntegers[i]); 485 | } 486 | 487 | for (size_t i = 0; i < kStringsCount; i++) { 488 | r1.strings.push_back(kStringValue); 489 | } 490 | 491 | std::unique_ptr out = avro::memoryOutputStream(); 492 | avro::EncoderPtr encoder = avro::binaryEncoder(); 493 | 494 | encoder->init(*out); 495 | avro::encode(*encoder, r1); 496 | 497 | auto serialized_size = out->byteCount(); 498 | 499 | std::unique_ptr in = avro::memoryInputStream(*out); 500 | avro::DecoderPtr decoder = avro::binaryDecoder(); 501 | 502 | decoder->init(*in); 503 | avro::decode(*decoder, r2); 504 | 505 | if (r1.ids != r2.ids || r1.strings != r2.strings || r2.ids.size() != kIntegers.size() 506 | || r2.strings.size() != kStringsCount) { 507 | throw std::logic_error("avro's case: deserialization failed"); 508 | } 509 | 510 | auto start = std::chrono::high_resolution_clock::now(); 511 | for (size_t i = 0; i < iterations; i++) { 512 | auto out = avro::memoryOutputStream(); 513 | auto encoder = avro::binaryEncoder(); 514 | encoder->init(*out); 515 | avro::encode(*encoder, r1); 516 | 517 | auto in = avro::memoryInputStream(*out); 518 | auto decoder = avro::binaryDecoder(); 519 | decoder->init(*in); 520 | avro::decode(*decoder, r2); 521 | } 522 | auto finish = std::chrono::high_resolution_clock::now(); 523 | auto duration = std::chrono::duration_cast(finish - start).count(); 524 | 525 | return Result("avro", "", serialized_size, duration); 526 | } 527 | 528 | Result 529 | flatbuffers_serialization_test(size_t iterations) 530 | { 531 | using namespace flatbuffers_test; 532 | 533 | std::vector> strings; 534 | strings.reserve(kStringsCount); 535 | 536 | flatbuffers::FlatBufferBuilder builder; 537 | for (size_t i = 0; i < kStringsCount; i++) { 538 | strings.push_back(builder.CreateString(kStringValue)); 539 | } 540 | 541 | auto ids_vec = builder.CreateVector(kIntegers); 542 | auto strings_vec = builder.CreateVector(strings); 543 | auto r1 = CreateRecord(builder, ids_vec, strings_vec); 544 | 545 | builder.Finish(r1); 546 | 547 | auto p = reinterpret_cast(builder.GetBufferPointer()); 548 | auto sz = builder.GetSize(); 549 | std::vector buf(p, p + sz); 550 | 551 | auto r2 = GetRecord(buf.data()); 552 | if (r2->strings()->size() != kStringsCount || r2->ids()->size() != kIntegers.size()) { 553 | throw std::logic_error("flatbuffer's case: deserialization failed"); 554 | } 555 | 556 | auto size = builder.GetSize(); 557 | 558 | builder.ReleaseBufferPointer(); 559 | 560 | auto start = std::chrono::high_resolution_clock::now(); 561 | for (size_t i = 0; i < iterations; i++) { 562 | flatbuffers::FlatBufferBuilder builder; 563 | strings.clear(); 564 | 565 | for (size_t i = 0; i < kStringsCount; i++) { 566 | strings.push_back(builder.CreateString(kStringValue)); 567 | } 568 | 569 | auto ids_vec = builder.CreateVector(kIntegers); 570 | auto strings_vec = builder.CreateVector(strings); 571 | auto r1 = CreateRecord(builder, ids_vec, strings_vec); 572 | builder.Finish(r1); 573 | 574 | auto p = reinterpret_cast(builder.GetBufferPointer()); 575 | auto sz = builder.GetSize(); 576 | std::vector buf(p, p + sz); 577 | auto r2 = GetRecord(buf.data()); 578 | (void)r2->ids()[0]; 579 | 580 | builder.ReleaseBufferPointer(); 581 | } 582 | auto finish = std::chrono::high_resolution_clock::now(); 583 | auto duration = std::chrono::duration_cast(finish - start).count(); 584 | 585 | auto version = FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "." FLATBUFFERS_STRING( 586 | FLATBUFFERS_VERSION_MINOR) "." FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION); 587 | 588 | return Result("flatbuffers", version, size, duration); 589 | } 590 | 591 | template 592 | Result 593 | yas_serialization_test(size_t iterations) 594 | { 595 | using namespace yas_test; 596 | 597 | Record r1, r2; 598 | 599 | for (size_t i = 0; i < kIntegers.size(); i++) { 600 | r1.ids.push_back(kIntegers[i]); 601 | } 602 | 603 | for (size_t i = 0; i < kStringsCount; i++) { 604 | r1.strings.push_back(kStringValue); 605 | } 606 | 607 | std::string serialized; 608 | 609 | to_string(r1, serialized); 610 | from_string(r2, serialized); 611 | 612 | if (r1 != r2) { 613 | throw std::logic_error("yas' case: deserialization failed"); 614 | } 615 | 616 | std::string tag; 617 | 618 | if (opts & yas::compacted) { 619 | tag = "yas-compact"; 620 | } else { 621 | tag = "yas"; 622 | } 623 | 624 | auto start = std::chrono::high_resolution_clock::now(); 625 | for (size_t i = 0; i < iterations; i++) { 626 | yas::mem_ostream os; 627 | yas::binary_oarchive oa(os); 628 | oa& r1; 629 | 630 | yas::mem_istream is(os.get_intrusive_buffer()); 631 | yas::binary_iarchive ia(is); 632 | ia& r2; 633 | } 634 | auto finish = std::chrono::high_resolution_clock::now(); 635 | auto duration = std::chrono::duration_cast(finish - start).count(); 636 | 637 | return Result(tag, YAS_VERSION_STRING, serialized.size(), duration); 638 | } 639 | 640 | int 641 | main(int argc, char** argv) 642 | { 643 | GOOGLE_PROTOBUF_VERIFY_VERSION; 644 | 645 | auto args = parse_args(argc, argv); 646 | 647 | /*std::cout << "total size: " << sizeof(kIntegerValue) * kIntegersCount + kStringValue.size() * kStringsCount << 648 | * std::endl;*/ 649 | 650 | std::vector results; 651 | 652 | try { 653 | if (args.serializers.empty() || args.serializers.find("thrift-binary") != args.serializers.end()) { 654 | results.push_back(thrift_serialization_test(args.iterations, ThriftSerializationProto::Binary)); 655 | } 656 | 657 | if (args.serializers.empty() || args.serializers.find("thrift-compact") != args.serializers.end()) { 658 | results.push_back(thrift_serialization_test(args.iterations, ThriftSerializationProto::Compact)); 659 | } 660 | 661 | if (args.serializers.empty() || args.serializers.find("protobuf") != args.serializers.end()) { 662 | results.push_back(protobuf_serialization_test(args.iterations)); 663 | } 664 | 665 | if (args.serializers.empty() || args.serializers.find("capnproto") != args.serializers.end()) { 666 | results.push_back(capnproto_serialization_test(args.iterations)); 667 | } 668 | 669 | if (args.serializers.empty() || args.serializers.find("boost") != args.serializers.end()) { 670 | results.push_back(boost_serialization_test(args.iterations)); 671 | } 672 | 673 | if (args.serializers.empty() || args.serializers.find("msgpack") != args.serializers.end()) { 674 | results.push_back(msgpack_serialization_test(args.iterations)); 675 | } 676 | 677 | if (args.serializers.empty() || args.serializers.find("cereal") != args.serializers.end()) { 678 | results.push_back(cereal_serialization_test(args.iterations)); 679 | } 680 | 681 | if (args.serializers.empty() || args.serializers.find("avro") != args.serializers.end()) { 682 | results.push_back(avro_serialization_test(args.iterations)); 683 | } 684 | 685 | if (args.serializers.empty() || args.serializers.find("flatbuffers") != args.serializers.end()) { 686 | results.push_back(flatbuffers_serialization_test(args.iterations)); 687 | } 688 | 689 | if (args.serializers.empty() || args.serializers.find("yas") != args.serializers.end()) { 690 | results.push_back(yas_serialization_test(args.iterations)); 691 | } 692 | 693 | if (args.serializers.empty() || args.serializers.find("yas-compact") != args.serializers.end()) { 694 | results.push_back(yas_serialization_test(args.iterations)); 695 | } 696 | } catch (std::exception& exc) { 697 | std::cerr << "Error: " << exc.what() << std::endl; 698 | return EXIT_FAILURE; 699 | } 700 | 701 | print_results(args, results); 702 | 703 | google::protobuf::ShutdownProtobufLibrary(); 704 | 705 | return EXIT_SUCCESS; 706 | } 707 | -------------------------------------------------------------------------------- /boost/record.cpp: -------------------------------------------------------------------------------- 1 | #include "boost/record.hpp" 2 | 3 | namespace boost_test { 4 | 5 | void 6 | to_string(const Record &record, std::string &data) 7 | { 8 | std::ostringstream stream; 9 | boost::archive::binary_oarchive archiver(stream); 10 | archiver << record; 11 | 12 | data = stream.str(); 13 | } 14 | 15 | void 16 | from_string(Record &record, const std::string &data) 17 | { 18 | std::stringstream stream(data); 19 | boost::archive::binary_iarchive archiver(stream); 20 | archiver >> record; 21 | } 22 | 23 | } // namespace 24 | -------------------------------------------------------------------------------- /boost/record.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __BOOST_RECORD_HPP_INCLUDED__ 2 | #define __BOOST_RECORD_HPP_INCLUDED__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | namespace boost_test { 24 | 25 | typedef std::vector Integers; 26 | typedef std::vector Strings; 27 | 28 | class Record { 29 | public: 30 | 31 | Integers ids; 32 | Strings strings; 33 | 34 | bool operator==(const Record &other) { 35 | return (ids == other.ids && strings == other.strings); 36 | } 37 | 38 | bool operator!=(const Record &other) { 39 | return !(*this == other); 40 | } 41 | 42 | private: 43 | 44 | friend class boost::serialization::access; 45 | 46 | template 47 | void serialize(Archive &ar, const unsigned int) 48 | { 49 | ar & ids; 50 | ar & strings; 51 | } 52 | }; 53 | 54 | void to_string(const Record &record, std::string &data); 55 | void from_string(Record &record, const std::string &data); 56 | 57 | } // namespace 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /capnproto/test.capnp.c++: -------------------------------------------------------------------------------- 1 | // Generated by Cap'n Proto compiler, DO NOT EDIT 2 | // source: test.capnp 3 | 4 | #include "test.capnp.h" 5 | 6 | namespace capnp { 7 | namespace schemas { 8 | static const ::capnp::_::AlignedData<55> b_b11f3695c22ca61e = { 9 | { 0, 0, 0, 0, 5, 0, 6, 0, 10 | 30, 166, 44, 194, 149, 54, 31, 177, 11 | 11, 0, 0, 0, 1, 0, 0, 0, 12 | 86, 151, 87, 178, 195, 228, 213, 234, 13 | 2, 0, 7, 0, 0, 0, 0, 0, 14 | 0, 0, 0, 0, 0, 0, 0, 0, 15 | 21, 0, 0, 0, 146, 0, 0, 0, 16 | 29, 0, 0, 0, 7, 0, 0, 0, 17 | 0, 0, 0, 0, 0, 0, 0, 0, 18 | 25, 0, 0, 0, 119, 0, 0, 0, 19 | 0, 0, 0, 0, 0, 0, 0, 0, 20 | 0, 0, 0, 0, 0, 0, 0, 0, 21 | 116, 101, 115, 116, 46, 99, 97, 112, 22 | 110, 112, 58, 82, 101, 99, 111, 114, 23 | 100, 0, 0, 0, 0, 0, 0, 0, 24 | 0, 0, 0, 0, 1, 0, 1, 0, 25 | 8, 0, 0, 0, 3, 0, 4, 0, 26 | 0, 0, 0, 0, 0, 0, 0, 0, 27 | 0, 0, 1, 0, 0, 0, 0, 0, 28 | 0, 0, 0, 0, 0, 0, 0, 0, 29 | 41, 0, 0, 0, 34, 0, 0, 0, 30 | 0, 0, 0, 0, 0, 0, 0, 0, 31 | 36, 0, 0, 0, 3, 0, 1, 0, 32 | 64, 0, 0, 0, 2, 0, 1, 0, 33 | 1, 0, 0, 0, 1, 0, 0, 0, 34 | 0, 0, 1, 0, 1, 0, 0, 0, 35 | 0, 0, 0, 0, 0, 0, 0, 0, 36 | 61, 0, 0, 0, 66, 0, 0, 0, 37 | 0, 0, 0, 0, 0, 0, 0, 0, 38 | 56, 0, 0, 0, 3, 0, 1, 0, 39 | 84, 0, 0, 0, 2, 0, 1, 0, 40 | 105, 100, 115, 0, 0, 0, 0, 0, 41 | 14, 0, 0, 0, 0, 0, 0, 0, 42 | 0, 0, 0, 0, 0, 0, 0, 0, 43 | 0, 0, 0, 0, 0, 0, 0, 0, 44 | 0, 0, 0, 0, 3, 0, 1, 0, 45 | 5, 0, 0, 0, 0, 0, 0, 0, 46 | 0, 0, 0, 0, 0, 0, 0, 0, 47 | 0, 0, 0, 0, 0, 0, 0, 0, 48 | 0, 0, 0, 0, 0, 0, 0, 0, 49 | 14, 0, 0, 0, 0, 0, 0, 0, 50 | 0, 0, 0, 0, 0, 0, 0, 0, 51 | 0, 0, 0, 0, 0, 0, 0, 0, 52 | 115, 116, 114, 105, 110, 103, 115, 0, 53 | 14, 0, 0, 0, 0, 0, 0, 0, 54 | 0, 0, 0, 0, 0, 0, 0, 0, 55 | 0, 0, 0, 0, 0, 0, 0, 0, 56 | 0, 0, 0, 0, 3, 0, 1, 0, 57 | 12, 0, 0, 0, 0, 0, 0, 0, 58 | 0, 0, 0, 0, 0, 0, 0, 0, 59 | 0, 0, 0, 0, 0, 0, 0, 0, 60 | 0, 0, 0, 0, 0, 0, 0, 0, 61 | 14, 0, 0, 0, 0, 0, 0, 0, 62 | 0, 0, 0, 0, 0, 0, 0, 0, 63 | 0, 0, 0, 0, 0, 0, 0, 0, } 64 | }; 65 | ::capnp::word const* const bp_b11f3695c22ca61e = b_b11f3695c22ca61e.words; 66 | #if !CAPNP_LITE 67 | static const uint16_t m_b11f3695c22ca61e[] = {0, 1}; 68 | static const uint16_t i_b11f3695c22ca61e[] = {0, 1}; 69 | const ::capnp::_::RawSchema s_b11f3695c22ca61e = { 70 | 0xb11f3695c22ca61e, b_b11f3695c22ca61e.words, 55, nullptr, m_b11f3695c22ca61e, 71 | 0, 2, i_b11f3695c22ca61e, nullptr, nullptr, { &s_b11f3695c22ca61e, nullptr, nullptr, 0, 0, nullptr } 72 | }; 73 | #endif // !CAPNP_LITE 74 | } // namespace schemas 75 | } // namespace capnp 76 | 77 | // ======================================================================================= 78 | 79 | namespace capnp_test { 80 | 81 | // Record 82 | constexpr uint16_t Record::_capnpPrivate::dataWordSize; 83 | constexpr uint16_t Record::_capnpPrivate::pointerCount; 84 | #if !CAPNP_LITE 85 | constexpr ::capnp::Kind Record::_capnpPrivate::kind; 86 | constexpr ::capnp::_::RawSchema const* Record::_capnpPrivate::schema; 87 | #endif // !CAPNP_LITE 88 | 89 | 90 | } // namespace 91 | 92 | -------------------------------------------------------------------------------- /capnproto/test.capnp.h: -------------------------------------------------------------------------------- 1 | // Generated by Cap'n Proto compiler, DO NOT EDIT 2 | // source: test.capnp 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #if CAPNP_VERSION != 7000 10 | #error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." 11 | #endif 12 | 13 | 14 | namespace capnp { 15 | namespace schemas { 16 | 17 | CAPNP_DECLARE_SCHEMA(b11f3695c22ca61e); 18 | 19 | } // namespace schemas 20 | } // namespace capnp 21 | 22 | namespace capnp_test { 23 | 24 | struct Record { 25 | Record() = delete; 26 | 27 | class Reader; 28 | class Builder; 29 | class Pipeline; 30 | 31 | struct _capnpPrivate { 32 | CAPNP_DECLARE_STRUCT_HEADER(b11f3695c22ca61e, 0, 2) 33 | #if !CAPNP_LITE 34 | static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } 35 | #endif // !CAPNP_LITE 36 | }; 37 | }; 38 | 39 | // ======================================================================================= 40 | 41 | class Record::Reader { 42 | public: 43 | typedef Record Reads; 44 | 45 | Reader() = default; 46 | inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} 47 | 48 | inline ::capnp::MessageSize totalSize() const { 49 | return _reader.totalSize().asPublic(); 50 | } 51 | 52 | #if !CAPNP_LITE 53 | inline ::kj::StringTree toString() const { 54 | return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); 55 | } 56 | #endif // !CAPNP_LITE 57 | 58 | inline bool hasIds() const; 59 | inline ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>::Reader getIds() const; 60 | 61 | inline bool hasStrings() const; 62 | inline ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>::Reader getStrings() const; 63 | 64 | private: 65 | ::capnp::_::StructReader _reader; 66 | template 67 | friend struct ::capnp::ToDynamic_; 68 | template 69 | friend struct ::capnp::_::PointerHelpers; 70 | template 71 | friend struct ::capnp::List; 72 | friend class ::capnp::MessageBuilder; 73 | friend class ::capnp::Orphanage; 74 | }; 75 | 76 | class Record::Builder { 77 | public: 78 | typedef Record Builds; 79 | 80 | Builder() = delete; // Deleted to discourage incorrect usage. 81 | // You can explicitly initialize to nullptr instead. 82 | inline Builder(decltype(nullptr)) {} 83 | inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} 84 | inline operator Reader() const { return Reader(_builder.asReader()); } 85 | inline Reader asReader() const { return *this; } 86 | 87 | inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } 88 | #if !CAPNP_LITE 89 | inline ::kj::StringTree toString() const { return asReader().toString(); } 90 | #endif // !CAPNP_LITE 91 | 92 | inline bool hasIds(); 93 | inline ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>::Builder getIds(); 94 | inline void setIds( ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>::Reader value); 95 | inline void setIds(::kj::ArrayPtr value); 96 | inline ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>::Builder initIds(unsigned int size); 97 | inline void adoptIds(::capnp::Orphan< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>>&& value); 98 | inline ::capnp::Orphan< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>> disownIds(); 99 | 100 | inline bool hasStrings(); 101 | inline ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>::Builder getStrings(); 102 | inline void setStrings( ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>::Reader value); 103 | inline void setStrings(::kj::ArrayPtr value); 104 | inline ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>::Builder initStrings(unsigned int size); 105 | inline void adoptStrings(::capnp::Orphan< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>>&& value); 106 | inline ::capnp::Orphan< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>> disownStrings(); 107 | 108 | private: 109 | ::capnp::_::StructBuilder _builder; 110 | template 111 | friend struct ::capnp::ToDynamic_; 112 | friend class ::capnp::Orphanage; 113 | template 114 | friend struct ::capnp::_::PointerHelpers; 115 | }; 116 | 117 | #if !CAPNP_LITE 118 | class Record::Pipeline { 119 | public: 120 | typedef Record Pipelines; 121 | 122 | inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} 123 | inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) 124 | : _typeless(kj::mv(typeless)) {} 125 | 126 | private: 127 | ::capnp::AnyPointer::Pipeline _typeless; 128 | friend class ::capnp::PipelineHook; 129 | template 130 | friend struct ::capnp::ToDynamic_; 131 | }; 132 | #endif // !CAPNP_LITE 133 | 134 | // ======================================================================================= 135 | 136 | inline bool Record::Reader::hasIds() const { 137 | return !_reader.getPointerField( 138 | ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); 139 | } 140 | inline bool Record::Builder::hasIds() { 141 | return !_builder.getPointerField( 142 | ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); 143 | } 144 | inline ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>::Reader Record::Reader::getIds() const { 145 | return ::capnp::_::PointerHelpers< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>>::get(_reader.getPointerField( 146 | ::capnp::bounded<0>() * ::capnp::POINTERS)); 147 | } 148 | inline ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>::Builder Record::Builder::getIds() { 149 | return ::capnp::_::PointerHelpers< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>>::get(_builder.getPointerField( 150 | ::capnp::bounded<0>() * ::capnp::POINTERS)); 151 | } 152 | inline void Record::Builder::setIds( ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>::Reader value) { 153 | ::capnp::_::PointerHelpers< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>>::set(_builder.getPointerField( 154 | ::capnp::bounded<0>() * ::capnp::POINTERS), value); 155 | } 156 | inline void Record::Builder::setIds(::kj::ArrayPtr value) { 157 | ::capnp::_::PointerHelpers< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>>::set(_builder.getPointerField( 158 | ::capnp::bounded<0>() * ::capnp::POINTERS), value); 159 | } 160 | inline ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>::Builder Record::Builder::initIds(unsigned int size) { 161 | return ::capnp::_::PointerHelpers< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>>::init(_builder.getPointerField( 162 | ::capnp::bounded<0>() * ::capnp::POINTERS), size); 163 | } 164 | inline void Record::Builder::adoptIds( 165 | ::capnp::Orphan< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>>&& value) { 166 | ::capnp::_::PointerHelpers< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>>::adopt(_builder.getPointerField( 167 | ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); 168 | } 169 | inline ::capnp::Orphan< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>> Record::Builder::disownIds() { 170 | return ::capnp::_::PointerHelpers< ::capnp::List< ::int64_t, ::capnp::Kind::PRIMITIVE>>::disown(_builder.getPointerField( 171 | ::capnp::bounded<0>() * ::capnp::POINTERS)); 172 | } 173 | 174 | inline bool Record::Reader::hasStrings() const { 175 | return !_reader.getPointerField( 176 | ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); 177 | } 178 | inline bool Record::Builder::hasStrings() { 179 | return !_builder.getPointerField( 180 | ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); 181 | } 182 | inline ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>::Reader Record::Reader::getStrings() const { 183 | return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>>::get(_reader.getPointerField( 184 | ::capnp::bounded<1>() * ::capnp::POINTERS)); 185 | } 186 | inline ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>::Builder Record::Builder::getStrings() { 187 | return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>>::get(_builder.getPointerField( 188 | ::capnp::bounded<1>() * ::capnp::POINTERS)); 189 | } 190 | inline void Record::Builder::setStrings( ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>::Reader value) { 191 | ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>>::set(_builder.getPointerField( 192 | ::capnp::bounded<1>() * ::capnp::POINTERS), value); 193 | } 194 | inline void Record::Builder::setStrings(::kj::ArrayPtr value) { 195 | ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>>::set(_builder.getPointerField( 196 | ::capnp::bounded<1>() * ::capnp::POINTERS), value); 197 | } 198 | inline ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>::Builder Record::Builder::initStrings(unsigned int size) { 199 | return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>>::init(_builder.getPointerField( 200 | ::capnp::bounded<1>() * ::capnp::POINTERS), size); 201 | } 202 | inline void Record::Builder::adoptStrings( 203 | ::capnp::Orphan< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>>&& value) { 204 | ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>>::adopt(_builder.getPointerField( 205 | ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); 206 | } 207 | inline ::capnp::Orphan< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>> Record::Builder::disownStrings() { 208 | return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::Text, ::capnp::Kind::BLOB>>::disown(_builder.getPointerField( 209 | ::capnp::bounded<1>() * ::capnp::POINTERS)); 210 | } 211 | 212 | } // namespace 213 | 214 | -------------------------------------------------------------------------------- /cereal/record.cpp: -------------------------------------------------------------------------------- 1 | #include "cereal/record.hpp" 2 | 3 | namespace cereal_test { 4 | 5 | void 6 | to_string(const Record &record, std::string &data) 7 | { 8 | std::ostringstream stream; 9 | cereal::BinaryOutputArchive archive(stream); 10 | archive(record); 11 | data = stream.str(); 12 | } 13 | 14 | void 15 | from_string(Record &record, const std::string &data) 16 | { 17 | std::stringstream stream(data); 18 | cereal::BinaryInputArchive archive(stream); 19 | archive(record); 20 | } 21 | 22 | } // namespace 23 | -------------------------------------------------------------------------------- /cereal/record.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __CEREAL_RECORD_HPP_INCLUDED__ 2 | #define __CEREAL_RECORD_HPP_INCLUDED__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace cereal_test { 15 | 16 | typedef std::vector Integers; 17 | typedef std::vector Strings; 18 | 19 | class Record { 20 | public: 21 | 22 | Integers ids; 23 | Strings strings; 24 | 25 | bool operator==(const Record &other) { 26 | return (ids == other.ids && strings == other.strings); 27 | } 28 | 29 | bool operator!=(const Record &other) { 30 | return !(*this == other); 31 | } 32 | 33 | private: 34 | 35 | friend class cereal::access; 36 | 37 | template 38 | void serialize(Archive &archive) 39 | { 40 | archive(ids, strings); 41 | } 42 | }; 43 | 44 | void to_string(const Record &record, std::string &data); 45 | void from_string(Record &record, const std::string &data); 46 | 47 | } // namespace 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /data.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __DATA_HPP_INCLUDED__ 2 | #define __DATA_HPP_INCLUDED__ 3 | 4 | #include 5 | #include 6 | 7 | const size_t kStringsCount = 100; 8 | const std::string kStringValue = "shgfkghsdfjhgsfjhfgjhfgjsffghgsfdhgsfdfkdjhfioukjhkfdljgdfkgvjafdhasgdfwurtjkghfsdjkfg"; 9 | 10 | // clang-format off 11 | const std::vector kIntegers = { 12 | -7363025924956902506, 433747491, -1063289711, 13 | -3099617426797642053, -10, -28373, 14 | 56, -26152, 11187, 15 | 16848, 52, 21, 16 | -1507434656, -40, 1817515017, 17 | 1733359561, 34, -5848022735330443435, 18 | -2877218739042719860, -14312, 23, 19 | -26, -13627, 206, 20 | 6171277796506625478, 937414961, -9891, 21 | -122, 519378804, 79, 22 | 8, 34, -6130140954141921706, 23 | -73, -616005134, -5037253190769578767, 24 | 0, -1722533411, -654047289, 25 | -5814, -257712663, -87, 26 | -6247856385486233498, 4742432808147022328, -810583170, 27 | -22, 6569946999860187637, -22276, 28 | -2172499325432780121, -898744892, 1882785313, 29 | 67, -845249652572657056, -103, 30 | -1713893920, -803649978604894042, -368771773, 31 | -2885635929107858908, 24954, 1357532846405761876, 32 | 769985138, -6727, 3466300259955127320, 33 | 2230714975058449906, -13476, -19, 34 | 84, -25529, 7199838975151841639, 35 | 34, 1326261707, -2163, 36 | -8638513271658874509, -1065570052, -678072504, 37 | 544751144, 118, -1628126727, 38 | 122, -124, -64, 39 | -12790, 559970209, -18411, 40 | 36, -98453689293414928, 2381030868204480509, 41 | -4220, 8994822118835925427, 25947, 42 | -994516429, 29735, -75, 43 | -16257, 1755158791, 1931770885540470507, 44 | -114, 503040442223125581, -5642282595025354408, 45 | 501831335, -49, -794973920, 46 | 18, 7198923596506520233, -15162, 47 | 8864, 25625, -8256, 48 | -630542150, 28541, -100, 49 | -92, -7986092697978475564, 3175680640580073309, 50 | -1454692424, -31891, -63, 51 | -103, 8487358384832003816, -23, 52 | -589490175, -5552032683325052704, -64, 53 | -80, -838179120, 8947214309209989793, 54 | -77, -7411189781173852711, -11697, 55 | 13436, 1815247385, -2981, 56 | -8003717504228034722, 99, -3257811286542676197, 57 | -4506293477750347316, -2711, 6160405628721311283, 58 | 5, -1484233804362552782, -17226, 59 | 1402014380, 733176135, -100, 60 | 4500917704953902996, 18, 4866887786818606461, 61 | -16225, 71, -22197, 62 | 2405053731958747752, -5274, -2090003371, 63 | 369436529, 1358574860523487735, -319773871, 64 | 16641, 5063075396589477179, 52, 65 | -21466, -81335356, -119208745560659154, 66 | 21924, -1047970083662342224, -11013, 67 | 76, 2903978634660040404, -101, 68 | 6916945980630884447, -1303492917515564855, 5637, 69 | 2248, -2030728347, 64, 70 | 7925, -21779, 8123127443689130000, 71 | 1417036646, -39040821, 117123230, 72 | -32, -3724, -6344211701431602973, 73 | -438193563, -113, -1926548125, 74 | 28729, -15, 282434333, 75 | 7871549853186581381, -433592745, -1055677683, 76 | 17987, -83, 7754104478641525815, 77 | 613327974, 14303, -8140203062797588352, 78 | 1586717809361568140, -7393582019467132139, 5126447447975253192, 79 | 1048, -1043188811128220318, 107, 80 | 65, -4172277813576501980, 14, 81 | 35, 26, -1236985343, 82 | -15929, -15216, 878309091, 83 | -56, -2011310606, 16389, 84 | 660901290, -1862266658167057059, -2323661464700608064, 85 | 1791007818, -5279836060148389134, -5205385764500646601, 86 | -10347, 1193594059, 8052063426113313885, 87 | 244985862, -7077002144560125490, -8930213132096048131, 88 | -78, -27, -16260, 89 | -3414386987451750431, 756976161, -1709959030, 90 | -960927998945600368, -141710072, 23461, 91 | -7185717208481827041, -89, -120, 92 | -1307393865, 27698, -14165, 93 | -1172826903, -8622113791680402438, -9400, 94 | 8808312621540105568, -4020327146569329755, 30976, 95 | 1866740273, -8231, 316317859, 96 | 1805393137, 485604266, 72, 97 | 2454665038702183726, 2094270224, 5686021805018713204, 98 | -24844, 20365, -4282662953797348809, 99 | -4566794532077649548, -6280124553363717403, -50, 100 | 32, 1872404256, -89, 101 | 316075246, -26268, -4964651049131855299, 102 | -112, -8641327509012147836, -766536697, 103 | 5993067092994742370, 1988899656, 1987725073, 104 | -19950, -1893302419775054285, 121, 105 | 48, 1948768928, 53, 106 | -5243, 8738685391165513812, 365750484, 107 | -93, -671864471, 706255199, 108 | -8152, 83, -99, 109 | -9, -3788717718769360742, 1307431297108392162, 110 | 30, 8716, 1436862582, 111 | 676135215, 22558, -122, 112 | 2522141144230140132, 5576475, -758518299, 113 | 147370106, 4988483904228877116, 947995246, 114 | 1659982684302768005, -22312, -48, 115 | 62, 79, 8537214179102424324, 116 | -997135172, 875051761, -4848592808270937156, 117 | -7697574980447404268, -37, -38, 118 | -1242, 313438480, 11749, 119 | -2986, 2030066008, 45, 120 | 1395369669, 1700476845, -20, 121 | -1287110890, -90, 1508574604756731954, 122 | -26092, -3939205815465530879, -1187773708119651248, 123 | -25834, -1206523470, -53, 124 | -1592661607326053524, 18212, -33, 125 | -41, 84266565, -2, 126 | 571521241, -1636475055566264497, 891431496, 127 | 23912, 10555, 30153, 128 | 8030521545404037952, -6374825163279815327, 99, 129 | 5241879833101903522, -1882027021007931225, 2040976134, 130 | -3793021618212331483, 83, 5696250655933345190, 131 | 1925480131260232953, 9358, -22648, 132 | 25575, -648216540, -5019755232846076450, 133 | 18622, 97, 554376950, 134 | 21886, -54, 2494996710999596835, 135 | -68, 18589, 40, 136 | -177650370, -74, 6270, 137 | 7538349603945271910, 25441, -893046314, 138 | -276550117, -74, -1427284664, 139 | -1049203211, 1869751501, 1213046221332824865, 140 | -1043880054, 8765925747447038140, -370820427, 141 | -5345471357868845747, -26330, -1155922900, 142 | -18875, -7601800821521096438, -111, 143 | -36, -12, 5533825000284329250, 144 | 5580, 27733, -381021541, 145 | 1178839104, 449775459, -103, 146 | 2050845098, -7540, -56, 147 | -928281908, -20046, -39, 148 | 13864, -14159, -6270095092780779000, 149 | 351242396, -12, 22, 150 | 29, -5852080089825335588, -608640126283793658, 151 | -474696155, -16, -1714338066, 152 | 565158960, 17722, 3807577336920137242, 153 | 21464, -117, -1769932179, 154 | -6041961534343242191, -30, 12353, 155 | -21, -6687, 1870487103, 156 | 24573, 12314, 4684252076755731050, 157 | -5659, 27965, 91, 158 | -167679051461621384, -2617986404823401218, 5732516693149630710, 159 | 9355, 4644, -120, 160 | 1635415463, 361922141231153413, 2466639219506760025, 161 | 21393, 7213002110551451773, 3033342980902020619, 162 | -31, -7137143647102241872, 16, 163 | -69, 6, 1789633802, 164 | -1170546172, 111, 55, 165 | -17896, -13714, 4026166599181052037, 166 | 23950776344086454, 65, -2856, 167 | -23465, 31786, 1312811083154161657, 168 | 30348, -1361598898, 5359, 169 | 72, -10252, 8623, 170 | 632949786950606955, -1229307629, 8293273260624578598, 171 | 29463, 1567105724, -3707, 172 | -28435, 1074126623, 2034633745, 173 | 2083185667, -5710229132046966643, -25357, 174 | 1832738019, 4309, -4631, 175 | -9301, 20237, -596, 176 | 959424841, -5528099178530169963, 116, 177 | -30632, -1106867457977143514, -1475677156535008452, 178 | 31293, -16109, -2193967216581540557, 179 | -23002, 2427339250189791946, 1679407924, 180 | 6051529596673312178, -17, 8544, 181 | 8459, -88, -1725552087, 182 | 1285, 26448, 28484, 183 | -17, -41, 8369898813248345434, 184 | -2708157913359168058, 21622, 57, 185 | -7398224664586362004, 28570, -6474382546613242389, 186 | 31, 17798, -1863510699, 187 | -5518, 111, -1553296730, 188 | 448310778, -8772569120406406086, 15990, 189 | -28920, -22497, -11057, 190 | -103, 587231746, -2038804459132069098, 191 | 4613338714938013216, 108, -5615213890232996984, 192 | -936055357, -1065383251, -2294510694869443495, 193 | -1477126894, -1673055163, -14284, 194 | 25051, -3986940435767480559, 6041752349511510486, 195 | 8041915042501314792, -3985160511342754585, -4028224886874105532, 196 | 1052206264681358951, -3481428206376095861, -46, 197 | 11550, -44, -2079227272, 198 | 8719067110551671946, 1288444037, -25143, 199 | 13602, 18, 21291, 200 | 93, -23, -196800021, 201 | 809571975, -31727, 8763, 202 | -661706897555808507, 119, 31046, 203 | -609547460, 23341, -60, 204 | 6086126050563937403, 1895635109952004787, -13995, 205 | -242886322, 8, 18, 206 | -8976496123608892670, -79, -7244, 207 | 2339688347224492944, 1104183683, -41, 208 | -18494, -971434129, 8642919108023816312, 209 | 21499, 28530, 70, 210 | 17290, -840331438133652510, 1976117116, 211 | 1570886366568950127, -101, -4534101121505215989, 212 | 20200, -63, -272652970, 213 | -28978, -349332691866139426, -25699, 214 | -1462205442, 580911690, -6992751044112263311, 215 | -107, -4575786221323014929, -195654910, 216 | 24, -3835604712339792761, 1891312992, 217 | 3828669121105386371, 124, -361586698, 218 | -937894193, -993613123, 28859, 219 | -15, 5009707794877239135, -223733485, 220 | -1721452461, 574309197, 4782, 221 | 97, 85, -1171035587590439385, 222 | 8312, -927867487, -1292683344, 223 | 11282, -125, 27129, 224 | -10222, -4880, -1792231338, 225 | 3758318694067395058, -55, -84, 226 | -22923036, 4120698313340693392, -350, 227 | -1899045160, 6349610473498904829, -60, 228 | -7222845473356938029, 1047951567, -440818821, 229 | -1537767148, -88, 25578, 230 | -115, -243999549, -89, 231 | -5312811593689077629, -103, 26, 232 | -5027457524326464514, -721685921, 39, 233 | -1362543574, -7795, -46, 234 | 1218271119, 30705, -17514, 235 | -23702, 6734, 6840, 236 | 1667317608, -1661745750, 4, 237 | 8033680933281782118, 13401, -70, 238 | 1676130015, -2938419533750020834, -106, 239 | -27755449, -29397, -4929554532967162102, 240 | -9622, -14823, 3772308820372273715, 241 | 807060921, -70, -22540, 242 | 295102169980408575, 95, -11, 243 | 88, 14465, -6365560894511598451, 244 | 2012336419, -22616, -1459870277, 245 | -2042522915, 118, -9980, 246 | 1777954039, -882129585, -2656396557369034721, 247 | 3781997027662552168, -1168752842, 3148967521842022774, 248 | -1313696289, -37, -343582862, 249 | 1874767111, -3112175777304194208, 7806167555058347392, 250 | 100, -1895288719, 28, 251 | -26159, 112, -30987, 252 | 10776, 5232434611274207549, -21024, 253 | -4483430693608459193, -345575112, -5917612984938832379, 254 | 27328, 6730667831210033901, -2809111713636358967, 255 | -12131, 4822, 26781, 256 | 1764874174431404362, -5, 13527, 257 | 7051481596943853310, 1610476985, 8720, 258 | -20287, -2316801172356721072, -2912299227084801965, 259 | 106, 30330, 6618, 260 | -17862, 31142, 386494837, 261 | 52, -494106843, 83, 262 | -27348, -7719, 19660, 263 | 886520682, 8960, 31956, 264 | 7796428150878326604, 8017588419220571056, -541019595, 265 | -26284, -63, -7344218109931640833, 266 | 106, -2011965846, 69, 267 | -7361118335520743856, -27, 111, 268 | 7024055925625955713, -27008, 27548, 269 | -724609890, -54, -1377801640, 270 | 1220470256, -6671358653627050578, 1408981531, 271 | -17834, -29778, 2154, 272 | -1147751355, -1244589537, 18, 273 | -8995, 1323880117, 4826, 274 | 3738, -8381527448310097033, 880564802, 275 | -18758, -2007492304, 124, 276 | 4071608576664398793, 1334705552, -883131665, 277 | 33, -2784068839981465237, -37, 278 | -3292250044805079221, 111, 115, 279 | -505824416, -1329516325, 6863, 280 | -4161, -1484254646, -1647742965, 281 | -684154112, 111, 441361943, 282 | -6617, 1161471919, -29, 283 | 305662650, -1681699761, 44, 284 | -1583862705295675197, -12, -1474320271, 285 | 7936, -917167826, -3860079915840664976, 286 | -25661, 3477085156689013266, 42, 287 | -22, -539422308, -16010, 288 | 613115140, -69, 410916790, 289 | -17638, 304410071, 1930928152, 290 | -30701, -2531841024167117027, 28606, 291 | 3307060987245058821, 108, -82, 292 | -2122172733037128428, -30691, 3251187856144995874, 293 | 520138362, 13352, -1406753793, 294 | -12, -1553003040463479123, -424, 295 | 41, -7233602940428378715, 7686418650162863126, 296 | -78, -5181978843372623165, -4271415536440906941, 297 | -31167, -64, 25, 298 | 36, -56, 33, 299 | 1537572386, 52, 109, 300 | -88, -6332157348037570723, -9438, 301 | 7636254448930979739, 2233977254874917251, 7657, 302 | 2155349169311562054, 1166413491, 7444722622948486608, 303 | 69, 117, 27307, 304 | -44, -187114342, -20777, 305 | 1478383894, -3599951908972507624, 1641800999, 306 | -2645721906112636821, 6021605908604371589, 7303492435488755034, 307 | 1434331208, 1090637426, 5897, 308 | 68708828, 1529684989, -120, 309 | -3, 10317, -70, 310 | 1787, 103, 43, 311 | 7692320002016645775, 13556915, -3414, 312 | 1406705089, -303493095, -72, 313 | 141171389, 8086501342466353726, -20791, 314 | 91, 691745374, 908599936, 315 | -31, 14639, -60, 316 | 78, -86, 6603823110258632713, 317 | -618490520, -1693031242, -3933, 318 | -53, 2453457273625938952, 3902407010405367825, 319 | 571240036, 121, -39, 320 | -154065643, 606326497545505818, 33, 321 | -1684204429, -2351, -21, 322 | 104, 7409, 10084, 323 | -1859407104, 7161074596731158945, 54, 324 | -15176, 85, 8542258976263311155, 325 | -510822799, 2634223587363843425, -838882481452157821, 326 | 2085654442476583674, -7271513813046190366, 2971023759308078566, 327 | 48, -534232402, 121, 328 | 1676343143, 105, 739395768, 329 | -56, 2633309473271351540, 101, 330 | -669904691, 4664, 34, 331 | 20, 2838549427757326550, -5628, 332 | -98, -4576588524518425817, 112, 333 | -8274461191016336405, -13461, -58, 334 | -195317548, 85, -11575, 335 | 1346208021602232582, 1133160616, -1128900985, 336 | -3003, 26, -101, 337 | -82, -1951476431, -14, 338 | -6604659608414297734, -19725, 45, 339 | -8721911835838330030, 99, -19640, 340 | -763002527307034193, -1373418318317290504, -2, 341 | 0, -4267535866276109679, -12369, 342 | -1482097641, -1211973318, -8156336852661611782, 343 | 58226505165754587, 1862931288479886958, 83, 344 | -10440, -33, -18991, 345 | -102 346 | }; 347 | // clang-format on 348 | 349 | #endif 350 | -------------------------------------------------------------------------------- /flatbuffers/test_generated.h: -------------------------------------------------------------------------------- 1 | // automatically generated by the FlatBuffers compiler, do not modify 2 | 3 | 4 | #ifndef FLATBUFFERS_GENERATED_TEST_FLATBUFFERS_TEST_H_ 5 | #define FLATBUFFERS_GENERATED_TEST_FLATBUFFERS_TEST_H_ 6 | 7 | #include "flatbuffers/flatbuffers.h" 8 | 9 | namespace flatbuffers_test { 10 | 11 | struct Record; 12 | 13 | struct Record FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { 14 | enum { 15 | VT_IDS = 4, 16 | VT_STRINGS = 6 17 | }; 18 | const flatbuffers::Vector *ids() const { 19 | return GetPointer *>(VT_IDS); 20 | } 21 | const flatbuffers::Vector> *strings() const { 22 | return GetPointer> *>(VT_STRINGS); 23 | } 24 | bool Verify(flatbuffers::Verifier &verifier) const { 25 | return VerifyTableStart(verifier) && 26 | VerifyOffset(verifier, VT_IDS) && 27 | verifier.VerifyVector(ids()) && 28 | VerifyOffset(verifier, VT_STRINGS) && 29 | verifier.VerifyVector(strings()) && 30 | verifier.VerifyVectorOfStrings(strings()) && 31 | verifier.EndTable(); 32 | } 33 | }; 34 | 35 | struct RecordBuilder { 36 | flatbuffers::FlatBufferBuilder &fbb_; 37 | flatbuffers::uoffset_t start_; 38 | void add_ids(flatbuffers::Offset> ids) { 39 | fbb_.AddOffset(Record::VT_IDS, ids); 40 | } 41 | void add_strings(flatbuffers::Offset>> strings) { 42 | fbb_.AddOffset(Record::VT_STRINGS, strings); 43 | } 44 | explicit RecordBuilder(flatbuffers::FlatBufferBuilder &_fbb) 45 | : fbb_(_fbb) { 46 | start_ = fbb_.StartTable(); 47 | } 48 | RecordBuilder &operator=(const RecordBuilder &); 49 | flatbuffers::Offset Finish() { 50 | const auto end = fbb_.EndTable(start_); 51 | auto o = flatbuffers::Offset(end); 52 | return o; 53 | } 54 | }; 55 | 56 | inline flatbuffers::Offset CreateRecord( 57 | flatbuffers::FlatBufferBuilder &_fbb, 58 | flatbuffers::Offset> ids = 0, 59 | flatbuffers::Offset>> strings = 0) { 60 | RecordBuilder builder_(_fbb); 61 | builder_.add_strings(strings); 62 | builder_.add_ids(ids); 63 | return builder_.Finish(); 64 | } 65 | 66 | inline flatbuffers::Offset CreateRecordDirect( 67 | flatbuffers::FlatBufferBuilder &_fbb, 68 | const std::vector *ids = nullptr, 69 | const std::vector> *strings = nullptr) { 70 | return flatbuffers_test::CreateRecord( 71 | _fbb, 72 | ids ? _fbb.CreateVector(*ids) : 0, 73 | strings ? _fbb.CreateVector>(*strings) : 0); 74 | } 75 | 76 | inline const flatbuffers_test::Record *GetRecord(const void *buf) { 77 | return flatbuffers::GetRoot(buf); 78 | } 79 | 80 | inline const flatbuffers_test::Record *GetSizePrefixedRecord(const void *buf) { 81 | return flatbuffers::GetSizePrefixedRoot(buf); 82 | } 83 | 84 | inline bool VerifyRecordBuffer( 85 | flatbuffers::Verifier &verifier) { 86 | return verifier.VerifyBuffer(nullptr); 87 | } 88 | 89 | inline bool VerifySizePrefixedRecordBuffer( 90 | flatbuffers::Verifier &verifier) { 91 | return verifier.VerifySizePrefixedBuffer(nullptr); 92 | } 93 | 94 | inline void FinishRecordBuffer( 95 | flatbuffers::FlatBufferBuilder &fbb, 96 | flatbuffers::Offset root) { 97 | fbb.Finish(root); 98 | } 99 | 100 | inline void FinishSizePrefixedRecordBuffer( 101 | flatbuffers::FlatBufferBuilder &fbb, 102 | flatbuffers::Offset root) { 103 | fbb.FinishSizePrefixed(root); 104 | } 105 | 106 | } // namespace flatbuffers_test 107 | 108 | #endif // FLATBUFFERS_GENERATED_TEST_FLATBUFFERS_TEST_H_ 109 | -------------------------------------------------------------------------------- /images/graphs.R: -------------------------------------------------------------------------------- 1 | library(ggplot2) 2 | 3 | names.size <- c("thrift-binary", "thrift-compact", "protobuf", "boost", "msgpack", "cereal", "avro", "capnproto", "flatbuffers", "yas", "yas-compact") 4 | names.time <- c("thrift-binary", "thrift-compact", "protobuf", "boost", "msgpack", "cereal", "avro", "yas", "yas-compact") 5 | names.time2 <- c("capnproto", "flatbuffers") 6 | # data from the 1000000 simulations 7 | # for t in thrift-binary thrift-compact protobuf boost msgpack cereal avro yas yas-compact; do echo -n "$t: "; ./benchmark 1 $t | grep size | awk '{print $4}'; done 8 | size <- c( 9 | 17017 # thrift-binary 10 | ,13378 # thrift-compact 11 | ,16116 # protobuf 12 | ,17470 # boost 13 | ,13402 # msgpack 14 | ,17416 # cereal 15 | ,16384 # avro 16 | ,17768 # capnproto 17 | ,17632 # flatbuffers 18 | ,17416 # yas 19 | ,13321 # yas-compact 20 | ) 21 | # for t in thrift-binary thrift-compact protobuf boost msgpack cereal avro yas yas-compact; do rm -f /tmp/$t.time; echo -n "$t: "; for i in `seq 1 50`; do ./benchmark 1000000 $t | grep time | awk '{print $4}' >>/tmp/$t.time; done; awk '{ sum += $1 } END { print sum/50}' /tmp/$t.time; done 22 | time <- c( 23 | 1190.22 # thrift-binary 24 | ,3474.32 # thrift-compact 25 | ,2312.78 # protobuf 26 | ,1195.04 # boost 27 | ,2560.6 # msgpack 28 | ,1052.46 # cereal 29 | ,4488.18 # avro 30 | ,302.7 # yas 31 | ,2063.34 # yas-compact 32 | ) 33 | time2 <- c( 34 | 400.98 # capnproto 35 | ,491.5 # flatbuffers 36 | ) 37 | 38 | data.size <- as.data.frame(list(serializer = names.size, size = size)) 39 | data.time <- as.data.frame(list(serializer = names.time, time = time)) 40 | data.time2 <- as.data.frame(list(serializer = names.time2, time = time2)) 41 | 42 | ssize <- ggplot(data.size, aes(x = as.factor(serializer), y = size, fill = serializer)) + 43 | geom_bar(stat = "identity") + 44 | xlab("serializer") + 45 | ylab("size") + 46 | theme(axis.text.x = element_text(angle = 90, hjust = 1)) 47 | png(filename="size.png", width = 800, height = 600) 48 | plot(ssize) 49 | dev.off() 50 | 51 | stime <- ggplot(data.time, aes(x = as.factor(serializer), y = time, fill = serializer)) + 52 | geom_bar(stat = "identity") + 53 | xlab("serializer") + 54 | ylab("time") + 55 | theme(axis.text.x = element_text(angle = 90, hjust = 1)) 56 | png(filename="time.png", width = 800, height = 600) 57 | plot(stime) 58 | dev.off() 59 | 60 | stime2 <- ggplot(data.time2, aes(x = as.factor(serializer), y = time, fill = serializer)) + 61 | geom_bar(stat = "identity") + 62 | xlab("serializer") + 63 | ylab("time") + 64 | theme(axis.text.x = element_text(angle = 90, hjust = 1)) 65 | png(filename="time2.png", width = 800, height = 600) 66 | plot(stime2) 67 | dev.off() 68 | -------------------------------------------------------------------------------- /images/size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thekvs/cpp-serializers/1bf07190805f7f2a7baac769dfdba8e80307440b/images/size.png -------------------------------------------------------------------------------- /images/time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thekvs/cpp-serializers/1bf07190805f7f2a7baac769dfdba8e80307440b/images/time.png -------------------------------------------------------------------------------- /images/time2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thekvs/cpp-serializers/1bf07190805f7f2a7baac769dfdba8e80307440b/images/time2.png -------------------------------------------------------------------------------- /msgpack/record.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __MSGPACK_RECORD_HPP_INCLUDED__ 2 | #define __MSGPACK_RECORD_HPP_INCLUDED__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace msgpack_test { 12 | 13 | typedef std::vector Integers; 14 | typedef std::vector Strings; 15 | 16 | class Record { 17 | public: 18 | 19 | Integers ids; 20 | Strings strings; 21 | 22 | bool operator==(const Record &other) { 23 | return (ids == other.ids && strings == other.strings); 24 | } 25 | 26 | bool operator!=(const Record &other) { 27 | return !(*this == other); 28 | } 29 | 30 | MSGPACK_DEFINE(ids, strings); 31 | }; 32 | 33 | } // namespace 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /protobuf/test.pb.cc: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: test.proto 3 | 4 | #include "test.pb.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | // @@protoc_insertion_point(includes) 17 | #include 18 | 19 | namespace protobuf_test { 20 | class RecordDefaultTypeInternal { 21 | public: 22 | ::google::protobuf::internal::ExplicitlyConstructed _instance; 23 | } _Record_default_instance_; 24 | } // namespace protobuf_test 25 | static void InitDefaultsRecord_test_2eproto() { 26 | GOOGLE_PROTOBUF_VERIFY_VERSION; 27 | 28 | { 29 | void* ptr = &::protobuf_test::_Record_default_instance_; 30 | new (ptr) ::protobuf_test::Record(); 31 | ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); 32 | } 33 | ::protobuf_test::Record::InitAsDefaultInstance(); 34 | } 35 | 36 | ::google::protobuf::internal::SCCInfo<0> scc_info_Record_test_2eproto = 37 | {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsRecord_test_2eproto}, {}}; 38 | 39 | void InitDefaults_test_2eproto() { 40 | ::google::protobuf::internal::InitSCC(&scc_info_Record_test_2eproto.base); 41 | } 42 | 43 | ::google::protobuf::Metadata file_level_metadata_test_2eproto[1]; 44 | constexpr ::google::protobuf::EnumDescriptor const** file_level_enum_descriptors_test_2eproto = nullptr; 45 | constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_test_2eproto = nullptr; 46 | 47 | const ::google::protobuf::uint32 TableStruct_test_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { 48 | ~0u, // no _has_bits_ 49 | PROTOBUF_FIELD_OFFSET(::protobuf_test::Record, _internal_metadata_), 50 | ~0u, // no _extensions_ 51 | ~0u, // no _oneof_case_ 52 | ~0u, // no _weak_field_map_ 53 | PROTOBUF_FIELD_OFFSET(::protobuf_test::Record, ids_), 54 | PROTOBUF_FIELD_OFFSET(::protobuf_test::Record, strings_), 55 | }; 56 | static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { 57 | { 0, -1, sizeof(::protobuf_test::Record)}, 58 | }; 59 | 60 | static ::google::protobuf::Message const * const file_default_instances[] = { 61 | reinterpret_cast(&::protobuf_test::_Record_default_instance_), 62 | }; 63 | 64 | ::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_test_2eproto = { 65 | {}, AddDescriptors_test_2eproto, "test.proto", schemas, 66 | file_default_instances, TableStruct_test_2eproto::offsets, 67 | file_level_metadata_test_2eproto, 1, file_level_enum_descriptors_test_2eproto, file_level_service_descriptors_test_2eproto, 68 | }; 69 | 70 | const char descriptor_table_protodef_test_2eproto[] = 71 | "\n\ntest.proto\022\rprotobuf_test\"&\n\006Record\022\013\n" 72 | "\003ids\030\001 \003(\003\022\017\n\007strings\030\002 \003(\tb\006proto3" 73 | ; 74 | ::google::protobuf::internal::DescriptorTable descriptor_table_test_2eproto = { 75 | false, InitDefaults_test_2eproto, 76 | descriptor_table_protodef_test_2eproto, 77 | "test.proto", &assign_descriptors_table_test_2eproto, 75, 78 | }; 79 | 80 | void AddDescriptors_test_2eproto() { 81 | static constexpr ::google::protobuf::internal::InitFunc deps[1] = 82 | { 83 | }; 84 | ::google::protobuf::internal::AddDescriptors(&descriptor_table_test_2eproto, deps, 0); 85 | } 86 | 87 | // Force running AddDescriptors() at dynamic initialization time. 88 | static bool dynamic_init_dummy_test_2eproto = []() { AddDescriptors_test_2eproto(); return true; }(); 89 | namespace protobuf_test { 90 | 91 | // =================================================================== 92 | 93 | void Record::InitAsDefaultInstance() { 94 | } 95 | class Record::HasBitSetters { 96 | public: 97 | }; 98 | 99 | #if !defined(_MSC_VER) || _MSC_VER >= 1900 100 | const int Record::kIdsFieldNumber; 101 | const int Record::kStringsFieldNumber; 102 | #endif // !defined(_MSC_VER) || _MSC_VER >= 1900 103 | 104 | Record::Record() 105 | : ::google::protobuf::Message(), _internal_metadata_(nullptr) { 106 | SharedCtor(); 107 | // @@protoc_insertion_point(constructor:protobuf_test.Record) 108 | } 109 | Record::Record(const Record& from) 110 | : ::google::protobuf::Message(), 111 | _internal_metadata_(nullptr), 112 | ids_(from.ids_), 113 | strings_(from.strings_) { 114 | _internal_metadata_.MergeFrom(from._internal_metadata_); 115 | // @@protoc_insertion_point(copy_constructor:protobuf_test.Record) 116 | } 117 | 118 | void Record::SharedCtor() { 119 | ::google::protobuf::internal::InitSCC( 120 | &scc_info_Record_test_2eproto.base); 121 | } 122 | 123 | Record::~Record() { 124 | // @@protoc_insertion_point(destructor:protobuf_test.Record) 125 | SharedDtor(); 126 | } 127 | 128 | void Record::SharedDtor() { 129 | } 130 | 131 | void Record::SetCachedSize(int size) const { 132 | _cached_size_.Set(size); 133 | } 134 | const Record& Record::default_instance() { 135 | ::google::protobuf::internal::InitSCC(&::scc_info_Record_test_2eproto.base); 136 | return *internal_default_instance(); 137 | } 138 | 139 | 140 | void Record::Clear() { 141 | // @@protoc_insertion_point(message_clear_start:protobuf_test.Record) 142 | ::google::protobuf::uint32 cached_has_bits = 0; 143 | // Prevent compiler warnings about cached_has_bits being unused 144 | (void) cached_has_bits; 145 | 146 | ids_.Clear(); 147 | strings_.Clear(); 148 | _internal_metadata_.Clear(); 149 | } 150 | 151 | #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 152 | const char* Record::_InternalParse(const char* begin, const char* end, void* object, 153 | ::google::protobuf::internal::ParseContext* ctx) { 154 | auto msg = static_cast(object); 155 | ::google::protobuf::int32 size; (void)size; 156 | int depth; (void)depth; 157 | ::google::protobuf::uint32 tag; 158 | ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end; 159 | auto ptr = begin; 160 | while (ptr < end) { 161 | ptr = ::google::protobuf::io::Parse32(ptr, &tag); 162 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 163 | switch (tag >> 3) { 164 | // repeated int64 ids = 1; 165 | case 1: { 166 | if (static_cast<::google::protobuf::uint8>(tag) == 10) { 167 | ptr = ::google::protobuf::io::ReadSize(ptr, &size); 168 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 169 | parser_till_end = ::google::protobuf::internal::PackedInt64Parser; 170 | object = msg->mutable_ids(); 171 | if (size > end - ptr) goto len_delim_till_end; 172 | auto newend = ptr + size; 173 | if (size) ptr = parser_till_end(ptr, newend, object, ctx); 174 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend); 175 | break; 176 | } else if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual; 177 | do { 178 | msg->add_ids(::google::protobuf::internal::ReadVarint(&ptr)); 179 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 180 | if (ptr >= end) break; 181 | } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 8 && (ptr += 1)); 182 | break; 183 | } 184 | // repeated string strings = 2; 185 | case 2: { 186 | if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual; 187 | do { 188 | ptr = ::google::protobuf::io::ReadSize(ptr, &size); 189 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 190 | ctx->extra_parse_data().SetFieldName("protobuf_test.Record.strings"); 191 | object = msg->add_strings(); 192 | if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) { 193 | parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8; 194 | goto string_till_end; 195 | } 196 | GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx)); 197 | ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx); 198 | ptr += size; 199 | if (ptr >= end) break; 200 | } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 18 && (ptr += 1)); 201 | break; 202 | } 203 | default: { 204 | handle_unusual: 205 | if ((tag & 7) == 4 || tag == 0) { 206 | ctx->EndGroup(tag); 207 | return ptr; 208 | } 209 | auto res = UnknownFieldParse(tag, {_InternalParse, msg}, 210 | ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx); 211 | ptr = res.first; 212 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); 213 | if (res.second) return ptr; 214 | } 215 | } // switch 216 | } // while 217 | return ptr; 218 | string_till_end: 219 | static_cast<::std::string*>(object)->clear(); 220 | static_cast<::std::string*>(object)->reserve(size); 221 | goto len_delim_till_end; 222 | len_delim_till_end: 223 | return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg}, 224 | {parser_till_end, object}, size); 225 | } 226 | #else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 227 | bool Record::MergePartialFromCodedStream( 228 | ::google::protobuf::io::CodedInputStream* input) { 229 | #define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure 230 | ::google::protobuf::uint32 tag; 231 | // @@protoc_insertion_point(parse_start:protobuf_test.Record) 232 | for (;;) { 233 | ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); 234 | tag = p.first; 235 | if (!p.second) goto handle_unusual; 236 | switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { 237 | // repeated int64 ids = 1; 238 | case 1: { 239 | if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) { 240 | DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< 241 | ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( 242 | input, this->mutable_ids()))); 243 | } else if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) { 244 | DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< 245 | ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( 246 | 1, 10u, input, this->mutable_ids()))); 247 | } else { 248 | goto handle_unusual; 249 | } 250 | break; 251 | } 252 | 253 | // repeated string strings = 2; 254 | case 2: { 255 | if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) { 256 | DO_(::google::protobuf::internal::WireFormatLite::ReadString( 257 | input, this->add_strings())); 258 | DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( 259 | this->strings(this->strings_size() - 1).data(), 260 | static_cast(this->strings(this->strings_size() - 1).length()), 261 | ::google::protobuf::internal::WireFormatLite::PARSE, 262 | "protobuf_test.Record.strings")); 263 | } else { 264 | goto handle_unusual; 265 | } 266 | break; 267 | } 268 | 269 | default: { 270 | handle_unusual: 271 | if (tag == 0) { 272 | goto success; 273 | } 274 | DO_(::google::protobuf::internal::WireFormat::SkipField( 275 | input, tag, _internal_metadata_.mutable_unknown_fields())); 276 | break; 277 | } 278 | } 279 | } 280 | success: 281 | // @@protoc_insertion_point(parse_success:protobuf_test.Record) 282 | return true; 283 | failure: 284 | // @@protoc_insertion_point(parse_failure:protobuf_test.Record) 285 | return false; 286 | #undef DO_ 287 | } 288 | #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 289 | 290 | void Record::SerializeWithCachedSizes( 291 | ::google::protobuf::io::CodedOutputStream* output) const { 292 | // @@protoc_insertion_point(serialize_start:protobuf_test.Record) 293 | ::google::protobuf::uint32 cached_has_bits = 0; 294 | (void) cached_has_bits; 295 | 296 | // repeated int64 ids = 1; 297 | if (this->ids_size() > 0) { 298 | ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); 299 | output->WriteVarint32(_ids_cached_byte_size_.load( 300 | std::memory_order_relaxed)); 301 | } 302 | for (int i = 0, n = this->ids_size(); i < n; i++) { 303 | ::google::protobuf::internal::WireFormatLite::WriteInt64NoTag( 304 | this->ids(i), output); 305 | } 306 | 307 | // repeated string strings = 2; 308 | for (int i = 0, n = this->strings_size(); i < n; i++) { 309 | ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( 310 | this->strings(i).data(), static_cast(this->strings(i).length()), 311 | ::google::protobuf::internal::WireFormatLite::SERIALIZE, 312 | "protobuf_test.Record.strings"); 313 | ::google::protobuf::internal::WireFormatLite::WriteString( 314 | 2, this->strings(i), output); 315 | } 316 | 317 | if (_internal_metadata_.have_unknown_fields()) { 318 | ::google::protobuf::internal::WireFormat::SerializeUnknownFields( 319 | _internal_metadata_.unknown_fields(), output); 320 | } 321 | // @@protoc_insertion_point(serialize_end:protobuf_test.Record) 322 | } 323 | 324 | ::google::protobuf::uint8* Record::InternalSerializeWithCachedSizesToArray( 325 | ::google::protobuf::uint8* target) const { 326 | // @@protoc_insertion_point(serialize_to_array_start:protobuf_test.Record) 327 | ::google::protobuf::uint32 cached_has_bits = 0; 328 | (void) cached_has_bits; 329 | 330 | // repeated int64 ids = 1; 331 | if (this->ids_size() > 0) { 332 | target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( 333 | 1, 334 | ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, 335 | target); 336 | target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( 337 | _ids_cached_byte_size_.load(std::memory_order_relaxed), 338 | target); 339 | target = ::google::protobuf::internal::WireFormatLite:: 340 | WriteInt64NoTagToArray(this->ids_, target); 341 | } 342 | 343 | // repeated string strings = 2; 344 | for (int i = 0, n = this->strings_size(); i < n; i++) { 345 | ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( 346 | this->strings(i).data(), static_cast(this->strings(i).length()), 347 | ::google::protobuf::internal::WireFormatLite::SERIALIZE, 348 | "protobuf_test.Record.strings"); 349 | target = ::google::protobuf::internal::WireFormatLite:: 350 | WriteStringToArray(2, this->strings(i), target); 351 | } 352 | 353 | if (_internal_metadata_.have_unknown_fields()) { 354 | target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( 355 | _internal_metadata_.unknown_fields(), target); 356 | } 357 | // @@protoc_insertion_point(serialize_to_array_end:protobuf_test.Record) 358 | return target; 359 | } 360 | 361 | size_t Record::ByteSizeLong() const { 362 | // @@protoc_insertion_point(message_byte_size_start:protobuf_test.Record) 363 | size_t total_size = 0; 364 | 365 | if (_internal_metadata_.have_unknown_fields()) { 366 | total_size += 367 | ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( 368 | _internal_metadata_.unknown_fields()); 369 | } 370 | ::google::protobuf::uint32 cached_has_bits = 0; 371 | // Prevent compiler warnings about cached_has_bits being unused 372 | (void) cached_has_bits; 373 | 374 | // repeated int64 ids = 1; 375 | { 376 | size_t data_size = ::google::protobuf::internal::WireFormatLite:: 377 | Int64Size(this->ids_); 378 | if (data_size > 0) { 379 | total_size += 1 + 380 | ::google::protobuf::internal::WireFormatLite::Int32Size( 381 | static_cast<::google::protobuf::int32>(data_size)); 382 | } 383 | int cached_size = ::google::protobuf::internal::ToCachedSize(data_size); 384 | _ids_cached_byte_size_.store(cached_size, 385 | std::memory_order_relaxed); 386 | total_size += data_size; 387 | } 388 | 389 | // repeated string strings = 2; 390 | total_size += 1 * 391 | ::google::protobuf::internal::FromIntSize(this->strings_size()); 392 | for (int i = 0, n = this->strings_size(); i < n; i++) { 393 | total_size += ::google::protobuf::internal::WireFormatLite::StringSize( 394 | this->strings(i)); 395 | } 396 | 397 | int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); 398 | SetCachedSize(cached_size); 399 | return total_size; 400 | } 401 | 402 | void Record::MergeFrom(const ::google::protobuf::Message& from) { 403 | // @@protoc_insertion_point(generalized_merge_from_start:protobuf_test.Record) 404 | GOOGLE_DCHECK_NE(&from, this); 405 | const Record* source = 406 | ::google::protobuf::DynamicCastToGenerated( 407 | &from); 408 | if (source == nullptr) { 409 | // @@protoc_insertion_point(generalized_merge_from_cast_fail:protobuf_test.Record) 410 | ::google::protobuf::internal::ReflectionOps::Merge(from, this); 411 | } else { 412 | // @@protoc_insertion_point(generalized_merge_from_cast_success:protobuf_test.Record) 413 | MergeFrom(*source); 414 | } 415 | } 416 | 417 | void Record::MergeFrom(const Record& from) { 418 | // @@protoc_insertion_point(class_specific_merge_from_start:protobuf_test.Record) 419 | GOOGLE_DCHECK_NE(&from, this); 420 | _internal_metadata_.MergeFrom(from._internal_metadata_); 421 | ::google::protobuf::uint32 cached_has_bits = 0; 422 | (void) cached_has_bits; 423 | 424 | ids_.MergeFrom(from.ids_); 425 | strings_.MergeFrom(from.strings_); 426 | } 427 | 428 | void Record::CopyFrom(const ::google::protobuf::Message& from) { 429 | // @@protoc_insertion_point(generalized_copy_from_start:protobuf_test.Record) 430 | if (&from == this) return; 431 | Clear(); 432 | MergeFrom(from); 433 | } 434 | 435 | void Record::CopyFrom(const Record& from) { 436 | // @@protoc_insertion_point(class_specific_copy_from_start:protobuf_test.Record) 437 | if (&from == this) return; 438 | Clear(); 439 | MergeFrom(from); 440 | } 441 | 442 | bool Record::IsInitialized() const { 443 | return true; 444 | } 445 | 446 | void Record::Swap(Record* other) { 447 | if (other == this) return; 448 | InternalSwap(other); 449 | } 450 | void Record::InternalSwap(Record* other) { 451 | using std::swap; 452 | _internal_metadata_.Swap(&other->_internal_metadata_); 453 | ids_.InternalSwap(&other->ids_); 454 | strings_.InternalSwap(CastToBase(&other->strings_)); 455 | } 456 | 457 | ::google::protobuf::Metadata Record::GetMetadata() const { 458 | ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_test_2eproto); 459 | return ::file_level_metadata_test_2eproto[kIndexInFileMessages]; 460 | } 461 | 462 | 463 | // @@protoc_insertion_point(namespace_scope) 464 | } // namespace protobuf_test 465 | namespace google { 466 | namespace protobuf { 467 | template<> PROTOBUF_NOINLINE ::protobuf_test::Record* Arena::CreateMaybeMessage< ::protobuf_test::Record >(Arena* arena) { 468 | return Arena::CreateInternal< ::protobuf_test::Record >(arena); 469 | } 470 | } // namespace protobuf 471 | } // namespace google 472 | 473 | // @@protoc_insertion_point(global_scope) 474 | #include 475 | -------------------------------------------------------------------------------- /protobuf/test.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: test.proto 3 | 4 | #ifndef PROTOBUF_INCLUDED_test_2eproto 5 | #define PROTOBUF_INCLUDED_test_2eproto 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #if PROTOBUF_VERSION < 3007000 12 | #error This file was generated by a newer version of protoc which is 13 | #error incompatible with your Protocol Buffer headers. Please update 14 | #error your headers. 15 | #endif 16 | #if 3007000 < PROTOBUF_MIN_PROTOC_VERSION 17 | #error This file was generated by an older version of protoc which is 18 | #error incompatible with your Protocol Buffer headers. Please 19 | #error regenerate this file with a newer version of protoc. 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include // IWYU pragma: export 32 | #include // IWYU pragma: export 33 | #include 34 | // @@protoc_insertion_point(includes) 35 | #include 36 | #define PROTOBUF_INTERNAL_EXPORT_test_2eproto 37 | 38 | // Internal implementation detail -- do not use these members. 39 | struct TableStruct_test_2eproto { 40 | static const ::google::protobuf::internal::ParseTableField entries[] 41 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 42 | static const ::google::protobuf::internal::AuxillaryParseTableField aux[] 43 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 44 | static const ::google::protobuf::internal::ParseTable schema[1] 45 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 46 | static const ::google::protobuf::internal::FieldMetadata field_metadata[]; 47 | static const ::google::protobuf::internal::SerializationTable serialization_table[]; 48 | static const ::google::protobuf::uint32 offsets[]; 49 | }; 50 | void AddDescriptors_test_2eproto(); 51 | namespace protobuf_test { 52 | class Record; 53 | class RecordDefaultTypeInternal; 54 | extern RecordDefaultTypeInternal _Record_default_instance_; 55 | } // namespace protobuf_test 56 | namespace google { 57 | namespace protobuf { 58 | template<> ::protobuf_test::Record* Arena::CreateMaybeMessage<::protobuf_test::Record>(Arena*); 59 | } // namespace protobuf 60 | } // namespace google 61 | namespace protobuf_test { 62 | 63 | // =================================================================== 64 | 65 | class Record final : 66 | public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:protobuf_test.Record) */ { 67 | public: 68 | Record(); 69 | virtual ~Record(); 70 | 71 | Record(const Record& from); 72 | 73 | inline Record& operator=(const Record& from) { 74 | CopyFrom(from); 75 | return *this; 76 | } 77 | #if LANG_CXX11 78 | Record(Record&& from) noexcept 79 | : Record() { 80 | *this = ::std::move(from); 81 | } 82 | 83 | inline Record& operator=(Record&& from) noexcept { 84 | if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { 85 | if (this != &from) InternalSwap(&from); 86 | } else { 87 | CopyFrom(from); 88 | } 89 | return *this; 90 | } 91 | #endif 92 | static const ::google::protobuf::Descriptor* descriptor() { 93 | return default_instance().GetDescriptor(); 94 | } 95 | static const Record& default_instance(); 96 | 97 | static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY 98 | static inline const Record* internal_default_instance() { 99 | return reinterpret_cast( 100 | &_Record_default_instance_); 101 | } 102 | static constexpr int kIndexInFileMessages = 103 | 0; 104 | 105 | void Swap(Record* other); 106 | friend void swap(Record& a, Record& b) { 107 | a.Swap(&b); 108 | } 109 | 110 | // implements Message ---------------------------------------------- 111 | 112 | inline Record* New() const final { 113 | return CreateMaybeMessage(nullptr); 114 | } 115 | 116 | Record* New(::google::protobuf::Arena* arena) const final { 117 | return CreateMaybeMessage(arena); 118 | } 119 | void CopyFrom(const ::google::protobuf::Message& from) final; 120 | void MergeFrom(const ::google::protobuf::Message& from) final; 121 | void CopyFrom(const Record& from); 122 | void MergeFrom(const Record& from); 123 | PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; 124 | bool IsInitialized() const final; 125 | 126 | size_t ByteSizeLong() const final; 127 | #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 128 | static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx); 129 | ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; } 130 | #else 131 | bool MergePartialFromCodedStream( 132 | ::google::protobuf::io::CodedInputStream* input) final; 133 | #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 134 | void SerializeWithCachedSizes( 135 | ::google::protobuf::io::CodedOutputStream* output) const final; 136 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 137 | ::google::protobuf::uint8* target) const final; 138 | int GetCachedSize() const final { return _cached_size_.Get(); } 139 | 140 | private: 141 | void SharedCtor(); 142 | void SharedDtor(); 143 | void SetCachedSize(int size) const final; 144 | void InternalSwap(Record* other); 145 | private: 146 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 147 | return nullptr; 148 | } 149 | inline void* MaybeArenaPtr() const { 150 | return nullptr; 151 | } 152 | public: 153 | 154 | ::google::protobuf::Metadata GetMetadata() const final; 155 | 156 | // nested types ---------------------------------------------------- 157 | 158 | // accessors ------------------------------------------------------- 159 | 160 | // repeated int64 ids = 1; 161 | int ids_size() const; 162 | void clear_ids(); 163 | static const int kIdsFieldNumber = 1; 164 | ::google::protobuf::int64 ids(int index) const; 165 | void set_ids(int index, ::google::protobuf::int64 value); 166 | void add_ids(::google::protobuf::int64 value); 167 | const ::google::protobuf::RepeatedField< ::google::protobuf::int64 >& 168 | ids() const; 169 | ::google::protobuf::RepeatedField< ::google::protobuf::int64 >* 170 | mutable_ids(); 171 | 172 | // repeated string strings = 2; 173 | int strings_size() const; 174 | void clear_strings(); 175 | static const int kStringsFieldNumber = 2; 176 | const ::std::string& strings(int index) const; 177 | ::std::string* mutable_strings(int index); 178 | void set_strings(int index, const ::std::string& value); 179 | #if LANG_CXX11 180 | void set_strings(int index, ::std::string&& value); 181 | #endif 182 | void set_strings(int index, const char* value); 183 | void set_strings(int index, const char* value, size_t size); 184 | ::std::string* add_strings(); 185 | void add_strings(const ::std::string& value); 186 | #if LANG_CXX11 187 | void add_strings(::std::string&& value); 188 | #endif 189 | void add_strings(const char* value); 190 | void add_strings(const char* value, size_t size); 191 | const ::google::protobuf::RepeatedPtrField<::std::string>& strings() const; 192 | ::google::protobuf::RepeatedPtrField<::std::string>* mutable_strings(); 193 | 194 | // @@protoc_insertion_point(class_scope:protobuf_test.Record) 195 | private: 196 | class HasBitSetters; 197 | 198 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 199 | ::google::protobuf::RepeatedField< ::google::protobuf::int64 > ids_; 200 | mutable std::atomic _ids_cached_byte_size_; 201 | ::google::protobuf::RepeatedPtrField<::std::string> strings_; 202 | mutable ::google::protobuf::internal::CachedSize _cached_size_; 203 | friend struct ::TableStruct_test_2eproto; 204 | }; 205 | // =================================================================== 206 | 207 | 208 | // =================================================================== 209 | 210 | #ifdef __GNUC__ 211 | #pragma GCC diagnostic push 212 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 213 | #endif // __GNUC__ 214 | // Record 215 | 216 | // repeated int64 ids = 1; 217 | inline int Record::ids_size() const { 218 | return ids_.size(); 219 | } 220 | inline void Record::clear_ids() { 221 | ids_.Clear(); 222 | } 223 | inline ::google::protobuf::int64 Record::ids(int index) const { 224 | // @@protoc_insertion_point(field_get:protobuf_test.Record.ids) 225 | return ids_.Get(index); 226 | } 227 | inline void Record::set_ids(int index, ::google::protobuf::int64 value) { 228 | ids_.Set(index, value); 229 | // @@protoc_insertion_point(field_set:protobuf_test.Record.ids) 230 | } 231 | inline void Record::add_ids(::google::protobuf::int64 value) { 232 | ids_.Add(value); 233 | // @@protoc_insertion_point(field_add:protobuf_test.Record.ids) 234 | } 235 | inline const ::google::protobuf::RepeatedField< ::google::protobuf::int64 >& 236 | Record::ids() const { 237 | // @@protoc_insertion_point(field_list:protobuf_test.Record.ids) 238 | return ids_; 239 | } 240 | inline ::google::protobuf::RepeatedField< ::google::protobuf::int64 >* 241 | Record::mutable_ids() { 242 | // @@protoc_insertion_point(field_mutable_list:protobuf_test.Record.ids) 243 | return &ids_; 244 | } 245 | 246 | // repeated string strings = 2; 247 | inline int Record::strings_size() const { 248 | return strings_.size(); 249 | } 250 | inline void Record::clear_strings() { 251 | strings_.Clear(); 252 | } 253 | inline const ::std::string& Record::strings(int index) const { 254 | // @@protoc_insertion_point(field_get:protobuf_test.Record.strings) 255 | return strings_.Get(index); 256 | } 257 | inline ::std::string* Record::mutable_strings(int index) { 258 | // @@protoc_insertion_point(field_mutable:protobuf_test.Record.strings) 259 | return strings_.Mutable(index); 260 | } 261 | inline void Record::set_strings(int index, const ::std::string& value) { 262 | // @@protoc_insertion_point(field_set:protobuf_test.Record.strings) 263 | strings_.Mutable(index)->assign(value); 264 | } 265 | #if LANG_CXX11 266 | inline void Record::set_strings(int index, ::std::string&& value) { 267 | // @@protoc_insertion_point(field_set:protobuf_test.Record.strings) 268 | strings_.Mutable(index)->assign(std::move(value)); 269 | } 270 | #endif 271 | inline void Record::set_strings(int index, const char* value) { 272 | GOOGLE_DCHECK(value != nullptr); 273 | strings_.Mutable(index)->assign(value); 274 | // @@protoc_insertion_point(field_set_char:protobuf_test.Record.strings) 275 | } 276 | inline void Record::set_strings(int index, const char* value, size_t size) { 277 | strings_.Mutable(index)->assign( 278 | reinterpret_cast(value), size); 279 | // @@protoc_insertion_point(field_set_pointer:protobuf_test.Record.strings) 280 | } 281 | inline ::std::string* Record::add_strings() { 282 | // @@protoc_insertion_point(field_add_mutable:protobuf_test.Record.strings) 283 | return strings_.Add(); 284 | } 285 | inline void Record::add_strings(const ::std::string& value) { 286 | strings_.Add()->assign(value); 287 | // @@protoc_insertion_point(field_add:protobuf_test.Record.strings) 288 | } 289 | #if LANG_CXX11 290 | inline void Record::add_strings(::std::string&& value) { 291 | strings_.Add(std::move(value)); 292 | // @@protoc_insertion_point(field_add:protobuf_test.Record.strings) 293 | } 294 | #endif 295 | inline void Record::add_strings(const char* value) { 296 | GOOGLE_DCHECK(value != nullptr); 297 | strings_.Add()->assign(value); 298 | // @@protoc_insertion_point(field_add_char:protobuf_test.Record.strings) 299 | } 300 | inline void Record::add_strings(const char* value, size_t size) { 301 | strings_.Add()->assign(reinterpret_cast(value), size); 302 | // @@protoc_insertion_point(field_add_pointer:protobuf_test.Record.strings) 303 | } 304 | inline const ::google::protobuf::RepeatedPtrField<::std::string>& 305 | Record::strings() const { 306 | // @@protoc_insertion_point(field_list:protobuf_test.Record.strings) 307 | return strings_; 308 | } 309 | inline ::google::protobuf::RepeatedPtrField<::std::string>* 310 | Record::mutable_strings() { 311 | // @@protoc_insertion_point(field_mutable_list:protobuf_test.Record.strings) 312 | return &strings_; 313 | } 314 | 315 | #ifdef __GNUC__ 316 | #pragma GCC diagnostic pop 317 | #endif // __GNUC__ 318 | 319 | // @@protoc_insertion_point(namespace_scope) 320 | 321 | } // namespace protobuf_test 322 | 323 | // @@protoc_insertion_point(global_scope) 324 | 325 | #include 326 | #endif // PROTOBUF_INCLUDED_test_2eproto 327 | -------------------------------------------------------------------------------- /test.capnp: -------------------------------------------------------------------------------- 1 | @0xead5e4c3b2579756; 2 | 3 | $import "/capnp/c++.capnp".namespace("capnp_test"); 4 | 5 | struct Record { 6 | ids @0 :List(Int64); 7 | strings @1 :List(Text); 8 | } 9 | -------------------------------------------------------------------------------- /test.fbs: -------------------------------------------------------------------------------- 1 | namespace flatbuffers_test; 2 | 3 | table Record { 4 | ids:[long]; 5 | strings:[string]; 6 | } 7 | 8 | root_type Record; 9 | -------------------------------------------------------------------------------- /test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "record", 3 | "name": "Record", 4 | "fields": [ 5 | { 6 | "name": "ids", 7 | "type": { 8 | "type": "array", 9 | "items": "long" 10 | } 11 | }, 12 | { 13 | "name": "strings", 14 | "type": { 15 | "type": "array", 16 | "items": "string" 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /test.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package protobuf_test; 3 | 4 | message Record { 5 | repeated int64 ids = 1; 6 | repeated string strings = 2; 7 | } 8 | -------------------------------------------------------------------------------- /test.thrift: -------------------------------------------------------------------------------- 1 | namespace cpp thrift_test 2 | 3 | struct Record { 4 | 1: required list ids, 5 | 2: required list strings 6 | } 7 | -------------------------------------------------------------------------------- /thrift/gen-cpp/test_constants.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.12.0) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #include "test_constants.h" 8 | 9 | namespace thrift_test { 10 | 11 | const testConstants g_test_constants; 12 | 13 | testConstants::testConstants() { 14 | } 15 | 16 | } // namespace 17 | 18 | -------------------------------------------------------------------------------- /thrift/gen-cpp/test_constants.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.12.0) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #ifndef test_CONSTANTS_H 8 | #define test_CONSTANTS_H 9 | 10 | #include "test_types.h" 11 | 12 | namespace thrift_test { 13 | 14 | class testConstants { 15 | public: 16 | testConstants(); 17 | 18 | }; 19 | 20 | extern const testConstants g_test_constants; 21 | 22 | } // namespace 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /thrift/gen-cpp/test_types.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.12.0) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #include "test_types.h" 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace thrift_test { 15 | 16 | 17 | Record::~Record() throw() { 18 | } 19 | 20 | 21 | void Record::__set_ids(const std::vector & val) { 22 | this->ids = val; 23 | } 24 | 25 | void Record::__set_strings(const std::vector & val) { 26 | this->strings = val; 27 | } 28 | std::ostream& operator<<(std::ostream& out, const Record& obj) 29 | { 30 | obj.printTo(out); 31 | return out; 32 | } 33 | 34 | 35 | uint32_t Record::read(::apache::thrift::protocol::TProtocol* iprot) { 36 | 37 | ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 38 | uint32_t xfer = 0; 39 | std::string fname; 40 | ::apache::thrift::protocol::TType ftype; 41 | int16_t fid; 42 | 43 | xfer += iprot->readStructBegin(fname); 44 | 45 | using ::apache::thrift::protocol::TProtocolException; 46 | 47 | bool isset_ids = false; 48 | bool isset_strings = false; 49 | 50 | while (true) 51 | { 52 | xfer += iprot->readFieldBegin(fname, ftype, fid); 53 | if (ftype == ::apache::thrift::protocol::T_STOP) { 54 | break; 55 | } 56 | switch (fid) 57 | { 58 | case 1: 59 | if (ftype == ::apache::thrift::protocol::T_LIST) { 60 | { 61 | this->ids.clear(); 62 | uint32_t _size0; 63 | ::apache::thrift::protocol::TType _etype3; 64 | xfer += iprot->readListBegin(_etype3, _size0); 65 | this->ids.resize(_size0); 66 | uint32_t _i4; 67 | for (_i4 = 0; _i4 < _size0; ++_i4) 68 | { 69 | xfer += iprot->readI64(this->ids[_i4]); 70 | } 71 | xfer += iprot->readListEnd(); 72 | } 73 | isset_ids = true; 74 | } else { 75 | xfer += iprot->skip(ftype); 76 | } 77 | break; 78 | case 2: 79 | if (ftype == ::apache::thrift::protocol::T_LIST) { 80 | { 81 | this->strings.clear(); 82 | uint32_t _size5; 83 | ::apache::thrift::protocol::TType _etype8; 84 | xfer += iprot->readListBegin(_etype8, _size5); 85 | this->strings.resize(_size5); 86 | uint32_t _i9; 87 | for (_i9 = 0; _i9 < _size5; ++_i9) 88 | { 89 | xfer += iprot->readString(this->strings[_i9]); 90 | } 91 | xfer += iprot->readListEnd(); 92 | } 93 | isset_strings = true; 94 | } else { 95 | xfer += iprot->skip(ftype); 96 | } 97 | break; 98 | default: 99 | xfer += iprot->skip(ftype); 100 | break; 101 | } 102 | xfer += iprot->readFieldEnd(); 103 | } 104 | 105 | xfer += iprot->readStructEnd(); 106 | 107 | if (!isset_ids) 108 | throw TProtocolException(TProtocolException::INVALID_DATA); 109 | if (!isset_strings) 110 | throw TProtocolException(TProtocolException::INVALID_DATA); 111 | return xfer; 112 | } 113 | 114 | uint32_t Record::write(::apache::thrift::protocol::TProtocol* oprot) const { 115 | uint32_t xfer = 0; 116 | ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 117 | xfer += oprot->writeStructBegin("Record"); 118 | 119 | xfer += oprot->writeFieldBegin("ids", ::apache::thrift::protocol::T_LIST, 1); 120 | { 121 | xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->ids.size())); 122 | std::vector ::const_iterator _iter10; 123 | for (_iter10 = this->ids.begin(); _iter10 != this->ids.end(); ++_iter10) 124 | { 125 | xfer += oprot->writeI64((*_iter10)); 126 | } 127 | xfer += oprot->writeListEnd(); 128 | } 129 | xfer += oprot->writeFieldEnd(); 130 | 131 | xfer += oprot->writeFieldBegin("strings", ::apache::thrift::protocol::T_LIST, 2); 132 | { 133 | xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->strings.size())); 134 | std::vector ::const_iterator _iter11; 135 | for (_iter11 = this->strings.begin(); _iter11 != this->strings.end(); ++_iter11) 136 | { 137 | xfer += oprot->writeString((*_iter11)); 138 | } 139 | xfer += oprot->writeListEnd(); 140 | } 141 | xfer += oprot->writeFieldEnd(); 142 | 143 | xfer += oprot->writeFieldStop(); 144 | xfer += oprot->writeStructEnd(); 145 | return xfer; 146 | } 147 | 148 | void swap(Record &a, Record &b) { 149 | using ::std::swap; 150 | swap(a.ids, b.ids); 151 | swap(a.strings, b.strings); 152 | } 153 | 154 | Record::Record(const Record& other12) { 155 | ids = other12.ids; 156 | strings = other12.strings; 157 | } 158 | Record& Record::operator=(const Record& other13) { 159 | ids = other13.ids; 160 | strings = other13.strings; 161 | return *this; 162 | } 163 | void Record::printTo(std::ostream& out) const { 164 | using ::apache::thrift::to_string; 165 | out << "Record("; 166 | out << "ids=" << to_string(ids); 167 | out << ", " << "strings=" << to_string(strings); 168 | out << ")"; 169 | } 170 | 171 | } // namespace 172 | -------------------------------------------------------------------------------- /thrift/gen-cpp/test_types.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.12.0) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #ifndef test_TYPES_H 8 | #define test_TYPES_H 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | 21 | namespace thrift_test { 22 | 23 | class Record; 24 | 25 | 26 | class Record : public virtual ::apache::thrift::TBase { 27 | public: 28 | 29 | Record(const Record&); 30 | Record& operator=(const Record&); 31 | Record() { 32 | } 33 | 34 | virtual ~Record() throw(); 35 | std::vector ids; 36 | std::vector strings; 37 | 38 | void __set_ids(const std::vector & val); 39 | 40 | void __set_strings(const std::vector & val); 41 | 42 | bool operator == (const Record & rhs) const 43 | { 44 | if (!(ids == rhs.ids)) 45 | return false; 46 | if (!(strings == rhs.strings)) 47 | return false; 48 | return true; 49 | } 50 | bool operator != (const Record &rhs) const { 51 | return !(*this == rhs); 52 | } 53 | 54 | bool operator < (const Record & ) const; 55 | 56 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 57 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 58 | 59 | virtual void printTo(std::ostream& out) const; 60 | }; 61 | 62 | void swap(Record &a, Record &b); 63 | 64 | std::ostream& operator<<(std::ostream& out, const Record& obj); 65 | 66 | } // namespace 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /yas/record.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "yas/record.hpp" 3 | 4 | namespace yas_test { 5 | 6 | } // namespace 7 | -------------------------------------------------------------------------------- /yas/record.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __YAS_RECORD_HPP_INCLUDED__ 3 | #define __YAS_RECORD_HPP_INCLUDED__ 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace yas_test { 16 | 17 | typedef std::vector Integers; 18 | typedef std::vector Strings; 19 | 20 | struct Record { 21 | 22 | Integers ids; 23 | Strings strings; 24 | 25 | bool operator==(const Record &other) { 26 | return (ids == other.ids && strings == other.strings); 27 | } 28 | 29 | bool operator!=(const Record &other) { 30 | return !(*this == other); 31 | } 32 | 33 | template 34 | void serialize(Archive &ar) 35 | { 36 | ar & ids & strings; 37 | } 38 | }; 39 | 40 | template 41 | void to_string(const Record &record, std::string &data) { 42 | yas::mem_ostream os; 43 | yas::binary_oarchive oa(os); 44 | oa & record; 45 | 46 | auto buf = os.get_intrusive_buffer(); 47 | data.assign(buf.data, buf.size); 48 | } 49 | 50 | template 51 | void from_string(Record &record, const std::string &data) { 52 | yas::mem_istream is(data.c_str(), data.size()); 53 | yas::binary_iarchive ia(is); 54 | ia & record; 55 | } 56 | 57 | } // namespace 58 | 59 | #endif 60 | --------------------------------------------------------------------------------