Benchmark Cap'n Proto and boost serialization
Reviewers: florijan, mferencevic, buda, mculinovic Reviewed By: buda Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1273
This commit is contained in:
parent
fc6173b4e2
commit
ab574bf84f
4
.gitignore
vendored
4
.gitignore
vendored
@ -33,3 +33,7 @@ TAGS
|
|||||||
# Lisp compiled object code
|
# Lisp compiled object code
|
||||||
*.fas
|
*.fas
|
||||||
*.fasl
|
*.fasl
|
||||||
|
|
||||||
|
# Cap'n Proto geenrated files
|
||||||
|
*.capnp.c++
|
||||||
|
*.capnp.h
|
||||||
|
@ -150,6 +150,7 @@ include_directories(SYSTEM ${ANTLR4_INCLUDE_DIR})
|
|||||||
include_directories(SYSTEM ${BZIP2_INCLUDE_DIR})
|
include_directories(SYSTEM ${BZIP2_INCLUDE_DIR})
|
||||||
include_directories(SYSTEM ${ZLIB_INCLUDE_DIR})
|
include_directories(SYSTEM ${ZLIB_INCLUDE_DIR})
|
||||||
include_directories(SYSTEM ${ROCKSDB_INCLUDE_DIR})
|
include_directories(SYSTEM ${ROCKSDB_INCLUDE_DIR})
|
||||||
|
include_directories(SYSTEM ${CAPNP_INCLUDE_DIR})
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
# openCypher parser -----------------------------------------------------------
|
# openCypher parser -----------------------------------------------------------
|
||||||
|
@ -17,21 +17,21 @@
|
|||||||
mkdir build_debug
|
mkdir build_debug
|
||||||
cd build_debug
|
cd build_debug
|
||||||
cmake ..
|
cmake ..
|
||||||
TIMEOUT=1000 make -j$THREADS
|
TIMEOUT=1200 make -j$THREADS
|
||||||
|
|
||||||
# Build coverage binaries.
|
# Build coverage binaries.
|
||||||
cd ..
|
cd ..
|
||||||
mkdir build_coverage
|
mkdir build_coverage
|
||||||
cd build_coverage
|
cd build_coverage
|
||||||
cmake -DTEST_COVERAGE=ON ..
|
cmake -DTEST_COVERAGE=ON ..
|
||||||
TIMEOUT=1000 make -j$THREADS memgraph__unit
|
TIMEOUT=1200 make -j$THREADS memgraph__unit
|
||||||
|
|
||||||
# Build release binaries.
|
# Build release binaries.
|
||||||
cd ..
|
cd ..
|
||||||
mkdir build_release
|
mkdir build_release
|
||||||
cd build_release
|
cd build_release
|
||||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||||
TIMEOUT=1000 make -j$THREADS memgraph tools memgraph__macro_benchmark memgraph__stress memgraph__manual__card_fraud_generate_snapshot
|
TIMEOUT=1200 make -j$THREADS memgraph tools memgraph__macro_benchmark memgraph__stress memgraph__manual__card_fraud_generate_snapshot
|
||||||
|
|
||||||
# Generate distributed card fraud dataset.
|
# Generate distributed card fraud dataset.
|
||||||
cd ../tests/distributed/card_fraud
|
cd ../tests/distributed/card_fraud
|
||||||
@ -47,7 +47,7 @@
|
|||||||
mkdir build_release
|
mkdir build_release
|
||||||
cd build_release
|
cd build_release
|
||||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||||
TIMEOUT=1000 make -j$THREADS memgraph memgraph__macro_benchmark
|
TIMEOUT=1200 make -j$THREADS memgraph memgraph__macro_benchmark
|
||||||
|
|
||||||
|
|
||||||
# release build is the default one
|
# release build is the default one
|
||||||
@ -63,21 +63,21 @@
|
|||||||
mkdir build_debug
|
mkdir build_debug
|
||||||
cd build_debug
|
cd build_debug
|
||||||
cmake ..
|
cmake ..
|
||||||
TIMEOUT=1000 make -j$THREADS
|
TIMEOUT=1200 make -j$THREADS
|
||||||
|
|
||||||
# Build coverage binaries.
|
# Build coverage binaries.
|
||||||
cd ..
|
cd ..
|
||||||
mkdir build_coverage
|
mkdir build_coverage
|
||||||
cd build_coverage
|
cd build_coverage
|
||||||
cmake -DTEST_COVERAGE=ON ..
|
cmake -DTEST_COVERAGE=ON ..
|
||||||
TIMEOUT=1000 make -j$THREADS memgraph__unit
|
TIMEOUT=1200 make -j$THREADS memgraph__unit
|
||||||
|
|
||||||
# Build release binaries.
|
# Build release binaries.
|
||||||
cd ..
|
cd ..
|
||||||
mkdir build_release
|
mkdir build_release
|
||||||
cd build_release
|
cd build_release
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -DUSE_READLINE=OFF ..
|
cmake -DCMAKE_BUILD_TYPE=Release -DUSE_READLINE=OFF ..
|
||||||
TIMEOUT=1000 make -j$THREADS
|
TIMEOUT=1200 make -j$THREADS
|
||||||
|
|
||||||
# Create Debian package.
|
# Create Debian package.
|
||||||
mkdir output
|
mkdir output
|
||||||
|
@ -209,3 +209,27 @@ import_external_library(rocksdb STATIC
|
|||||||
CC=${CMAKE_C_COMPILER}
|
CC=${CMAKE_C_COMPILER}
|
||||||
CXX=${CMAKE_CXX_COMPILER}
|
CXX=${CMAKE_CXX_COMPILER}
|
||||||
INSTALL_COMMAND true)
|
INSTALL_COMMAND true)
|
||||||
|
|
||||||
|
# Setup Cap'n Proto
|
||||||
|
ExternalProject_Add(capnproto-proj
|
||||||
|
PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/capnproto
|
||||||
|
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/capnproto
|
||||||
|
BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/capnproto
|
||||||
|
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/configure
|
||||||
|
--prefix=${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local
|
||||||
|
--enable-shared=no --silent
|
||||||
|
CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER}
|
||||||
|
BUILD_COMMAND make -j${NPROC} check)
|
||||||
|
set(CAPNP_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local/include
|
||||||
|
CACHE FILEPATH "Path to capnproto include directory" FORCE)
|
||||||
|
set(CAPNP_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local/lib/libcapnp.a
|
||||||
|
CACHE FILEPATH "Path to capnproto library" FORCE)
|
||||||
|
set(KJ_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local/lib/libkj.a
|
||||||
|
CACHE FILEPATH "Path to kj library (used by capnproto)" FORCE)
|
||||||
|
import_library(capnp STATIC ${CAPNP_LIBRARY} capnproto-proj)
|
||||||
|
import_library(kj STATIC ${KJ_LIBRARY} capnproto-proj)
|
||||||
|
set(CAPNP_EXE ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local/bin/capnp
|
||||||
|
CACHE FILEPATH "Path to capnproto executable" FORCE)
|
||||||
|
set(CAPNP_CXX_EXE ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local/bin/capnpc-c++
|
||||||
|
CACHE FILEPATH "Path to capnproto c++ plugin executable" FORCE)
|
||||||
|
mark_as_advanced(CAPNP_INCLUDE_DIR CAPNP_LIBRARY KJ_LIBRARY CAPNP_EXE CAPNP_CXX_EXE)
|
||||||
|
@ -120,3 +120,10 @@ clone git://deps.memgraph.io/zlib.git zlib $zlib_tag
|
|||||||
|
|
||||||
rocksdb_tag="dbd8fa09b823826dd2a30bc119dad7a6fa9a4c6d" # v5.11.3 Mar 12, 2018
|
rocksdb_tag="dbd8fa09b823826dd2a30bc119dad7a6fa9a4c6d" # v5.11.3 Mar 12, 2018
|
||||||
clone git://deps.memgraph.io/rocksdb.git rocksdb $rocksdb_tag
|
clone git://deps.memgraph.io/rocksdb.git rocksdb $rocksdb_tag
|
||||||
|
|
||||||
|
# Cap'n Proto serialization (and RPC) lib
|
||||||
|
wget -nv http://deps.memgraph.io/capnproto-c++-0.6.1.tar.gz -O capnproto.tar.gz
|
||||||
|
tar -xzf capnproto.tar.gz
|
||||||
|
rm -rf capnproto
|
||||||
|
mv capnproto-c++-0.6.1 capnproto
|
||||||
|
rm capnproto.tar.gz
|
||||||
|
@ -95,13 +95,33 @@ function(add_lcp lcp_file)
|
|||||||
endfunction(add_lcp)
|
endfunction(add_lcp)
|
||||||
|
|
||||||
add_custom_target(generate_lcp DEPENDS ${generated_lcp_files})
|
add_custom_target(generate_lcp DEPENDS ${generated_lcp_files})
|
||||||
|
|
||||||
|
# Use this function to add each capnp file to generation. This way each file is
|
||||||
|
# standalone and we avoid recompiling everything.
|
||||||
|
# NOTE: memgraph_src_files and generated_capnp_files are globally updated.
|
||||||
|
function(add_capnp capnp_src_file)
|
||||||
|
set(cpp_file ${CMAKE_CURRENT_SOURCE_DIR}/${capnp_src_file}.c++)
|
||||||
|
set(h_file ${CMAKE_CURRENT_SOURCE_DIR}/${capnp_src_file}.h)
|
||||||
|
add_custom_command(OUTPUT ${cpp_file} ${h_file}
|
||||||
|
COMMAND ${CAPNP_EXE} compile -o${CAPNP_CXX_EXE} ${capnp_src_file}
|
||||||
|
DEPENDS ${capnp_src_file} capnproto-proj
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
# Update *global* generated_capnp_files
|
||||||
|
set(generated_capnp_files ${generated_capnp_files} ${cpp_file} ${h_file} PARENT_SCOPE)
|
||||||
|
# Update *global* memgraph_src_files
|
||||||
|
set(memgraph_src_files ${memgraph_src_files} ${cpp_file} PARENT_SCOPE)
|
||||||
|
endfunction(add_capnp)
|
||||||
|
|
||||||
|
add_capnp(query/frontend/semantic/symbol.capnp)
|
||||||
|
|
||||||
|
add_custom_target(generate_capnp DEPENDS ${generated_capnp_files})
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
|
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
|
||||||
|
|
||||||
# memgraph_lib depend on these libraries
|
# memgraph_lib depend on these libraries
|
||||||
set(MEMGRAPH_ALL_LIBS stdc++fs Threads::Threads fmt cppitertools
|
set(MEMGRAPH_ALL_LIBS stdc++fs Threads::Threads fmt cppitertools
|
||||||
antlr_opencypher_parser_lib dl glog gflags
|
antlr_opencypher_parser_lib dl glog gflags capnp kj
|
||||||
${Boost_IOSTREAMS_LIBRARY_RELEASE}
|
${Boost_IOSTREAMS_LIBRARY_RELEASE}
|
||||||
${Boost_SERIALIZATION_LIBRARY_RELEASE})
|
${Boost_SERIALIZATION_LIBRARY_RELEASE})
|
||||||
|
|
||||||
@ -120,6 +140,7 @@ add_library(memgraph_lib STATIC ${memgraph_src_files})
|
|||||||
target_link_libraries(memgraph_lib ${MEMGRAPH_ALL_LIBS})
|
target_link_libraries(memgraph_lib ${MEMGRAPH_ALL_LIBS})
|
||||||
add_dependencies(memgraph_lib generate_opencypher_parser)
|
add_dependencies(memgraph_lib generate_opencypher_parser)
|
||||||
add_dependencies(memgraph_lib generate_lcp)
|
add_dependencies(memgraph_lib generate_lcp)
|
||||||
|
add_dependencies(memgraph_lib generate_capnp)
|
||||||
|
|
||||||
# STATIC library used to store key-value pairs
|
# STATIC library used to store key-value pairs
|
||||||
# TODO: Create a utils lib to link with, and remove utils/file.cpp.
|
# TODO: Create a utils lib to link with, and remove utils/file.cpp.
|
||||||
|
21
src/query/frontend/semantic/symbol.capnp
Normal file
21
src/query/frontend/semantic/symbol.capnp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
@0x93c1dcee84e93b76;
|
||||||
|
|
||||||
|
using Cxx = import "/capnp/c++.capnp";
|
||||||
|
$Cxx.namespace("query::capnp");
|
||||||
|
|
||||||
|
struct Symbol {
|
||||||
|
enum Type {
|
||||||
|
any @0;
|
||||||
|
vertex @1;
|
||||||
|
edge @2;
|
||||||
|
path @3;
|
||||||
|
number @4;
|
||||||
|
edgeList @5;
|
||||||
|
}
|
||||||
|
|
||||||
|
name @0 :Text;
|
||||||
|
position @1 :Int32;
|
||||||
|
type @2 :Type;
|
||||||
|
userDeclared @3 :Bool;
|
||||||
|
tokenPosition @4 :Int32;
|
||||||
|
}
|
143
tests/benchmark/serialization.cpp
Normal file
143
tests/benchmark/serialization.cpp
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
|
||||||
|
#include "boost/archive/binary_iarchive.hpp"
|
||||||
|
#include "boost/archive/binary_oarchive.hpp"
|
||||||
|
#include "boost/serialization/vector.hpp"
|
||||||
|
|
||||||
|
#include <capnp/serialize.h>
|
||||||
|
#include <kj/std/iostream.h>
|
||||||
|
|
||||||
|
#include "query/frontend/semantic/symbol.capnp.h"
|
||||||
|
#include "query/frontend/semantic/symbol.hpp"
|
||||||
|
|
||||||
|
class SymbolVectorFixture : public benchmark::Fixture {
|
||||||
|
protected:
|
||||||
|
std::vector<query::Symbol> symbols_;
|
||||||
|
|
||||||
|
void SetUp(const benchmark::State &state) override {
|
||||||
|
using Type = ::query::Symbol::Type;
|
||||||
|
std::vector<Type> types{Type::Any, Type::Vertex, Type::Edge,
|
||||||
|
Type::Path, Type::Number, Type::EdgeList};
|
||||||
|
symbols_.reserve(state.range(0));
|
||||||
|
for (int i = 0; i < state.range(0); ++i) {
|
||||||
|
std::string name = "Symbol " + std::to_string(i);
|
||||||
|
bool user_declared = i % 2;
|
||||||
|
auto type = types[i % types.size()];
|
||||||
|
symbols_.emplace_back(name, i, user_declared, type, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown(const benchmark::State &) override { symbols_.clear(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
BENCHMARK_DEFINE_F(SymbolVectorFixture, BoostSerial)(benchmark::State &state) {
|
||||||
|
while (state.KeepRunning()) {
|
||||||
|
std::stringstream stream(std::ios_base::out | std::ios_base::binary);
|
||||||
|
{
|
||||||
|
boost::archive::binary_oarchive archive(stream);
|
||||||
|
archive << symbols_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK_DEFINE_F(SymbolVectorFixture, BoostDeserial)
|
||||||
|
(benchmark::State &state) {
|
||||||
|
auto serialize = [this]() {
|
||||||
|
std::stringstream stream(std::ios_base::in | std::ios_base::out |
|
||||||
|
std::ios_base::binary);
|
||||||
|
{
|
||||||
|
boost::archive::binary_oarchive archive(stream);
|
||||||
|
archive << symbols_;
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
};
|
||||||
|
while (state.KeepRunning()) {
|
||||||
|
state.PauseTiming();
|
||||||
|
auto stream = serialize();
|
||||||
|
state.ResumeTiming();
|
||||||
|
std::vector<query::Symbol> symbols;
|
||||||
|
{
|
||||||
|
boost::archive::binary_iarchive archive(stream);
|
||||||
|
archive >> symbols;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolVectorToCapnpMessage(const std::vector<query::Symbol> &symbols,
|
||||||
|
capnp::MessageBuilder &message) {
|
||||||
|
auto symbols_builder =
|
||||||
|
message.initRoot<capnp::List<query::capnp::Symbol>>(symbols.size());
|
||||||
|
for (int i = 0; i < symbols.size(); ++i) {
|
||||||
|
const auto &sym = symbols[i];
|
||||||
|
query::capnp::Symbol::Builder sym_builder = symbols_builder[i];
|
||||||
|
sym_builder.setName(sym.name());
|
||||||
|
sym_builder.setPosition(sym.position());
|
||||||
|
sym_builder.setType(query::capnp::Symbol::Type::ANY);
|
||||||
|
sym_builder.setUserDeclared(sym.user_declared());
|
||||||
|
sym_builder.setTokenPosition(sym.token_position());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream SerializeCapnpSymbolVector(
|
||||||
|
const std::vector<query::Symbol> &symbols) {
|
||||||
|
std::stringstream stream(std::ios_base::in | std::ios_base::out |
|
||||||
|
std::ios_base::binary);
|
||||||
|
{
|
||||||
|
capnp::MallocMessageBuilder message;
|
||||||
|
SymbolVectorToCapnpMessage(symbols, message);
|
||||||
|
kj::std::StdOutputStream std_stream(stream);
|
||||||
|
kj::BufferedOutputStreamWrapper buffered_stream(std_stream);
|
||||||
|
writeMessage(buffered_stream, message);
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK_DEFINE_F(SymbolVectorFixture, CapnpSerial)(benchmark::State &state) {
|
||||||
|
while (state.KeepRunning()) {
|
||||||
|
SerializeCapnpSymbolVector(symbols_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK_DEFINE_F(SymbolVectorFixture, CapnpDeserial)
|
||||||
|
(benchmark::State &state) {
|
||||||
|
while (state.KeepRunning()) {
|
||||||
|
state.PauseTiming();
|
||||||
|
auto stream = SerializeCapnpSymbolVector(symbols_);
|
||||||
|
state.ResumeTiming();
|
||||||
|
kj::std::StdInputStream std_stream(stream);
|
||||||
|
capnp::InputStreamMessageReader message(std_stream);
|
||||||
|
auto symbols_reader = message.getRoot<capnp::List<query::capnp::Symbol>>();
|
||||||
|
std::vector<query::Symbol> symbols;
|
||||||
|
symbols.reserve(symbols_reader.size());
|
||||||
|
for (const auto &sym : symbols_reader) {
|
||||||
|
symbols.emplace_back(sym.getName().cStr(), sym.getPosition(),
|
||||||
|
sym.getUserDeclared(), query::Symbol::Type::Any,
|
||||||
|
sym.getTokenPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK_REGISTER_F(SymbolVectorFixture, BoostSerial)
|
||||||
|
->RangeMultiplier(4)
|
||||||
|
->Range(4, 1 << 12)
|
||||||
|
->Unit(benchmark::kNanosecond);
|
||||||
|
|
||||||
|
BENCHMARK_REGISTER_F(SymbolVectorFixture, CapnpSerial)
|
||||||
|
->RangeMultiplier(4)
|
||||||
|
->Range(4, 1 << 12)
|
||||||
|
->Unit(benchmark::kNanosecond);
|
||||||
|
|
||||||
|
BENCHMARK_REGISTER_F(SymbolVectorFixture, BoostDeserial)
|
||||||
|
->RangeMultiplier(4)
|
||||||
|
->Range(4, 1 << 12)
|
||||||
|
->Unit(benchmark::kNanosecond);
|
||||||
|
|
||||||
|
BENCHMARK_REGISTER_F(SymbolVectorFixture, CapnpDeserial)
|
||||||
|
->RangeMultiplier(4)
|
||||||
|
->Range(4, 1 << 12)
|
||||||
|
->Unit(benchmark::kNanosecond);
|
||||||
|
|
||||||
|
BENCHMARK_MAIN();
|
Loading…
Reference in New Issue
Block a user