From 19bec4acc891590585393f35f9cb9396594e3e2b Mon Sep 17 00:00:00 2001 From: Mislav Bradac <mislav.bradac@memgraph.io> Date: Thu, 24 Aug 2017 15:45:49 +0200 Subject: [PATCH] Fix expansion benchmark Reviewers: florijan, mferencevic, teon.banek, buda Reviewed By: florijan Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D708 --- .../concurrent/skiplist_gc.hpp | 6 ++++ src/database/dbms.hpp | 21 ++++++++++++ tests/benchmark/expansion.cpp | 32 ++++++++++--------- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/data_structures/concurrent/skiplist_gc.hpp b/src/data_structures/concurrent/skiplist_gc.hpp index 43cda570a..df0170502 100644 --- a/src/data_structures/concurrent/skiplist_gc.hpp +++ b/src/data_structures/concurrent/skiplist_gc.hpp @@ -49,6 +49,12 @@ class SkipListGC { * @brief - Returns instance of executioner shared between all SkipLists. */ auto &GetExecutioner() { + // TODO: Even though executioner is static, there are multiple instance: + // one for each TNode param type. We probably don't want that kind of + // behavior. Static variables with nontrivial destructor create subtle bugs + // because of their order of destruction. For example of one bug take a look + // at documentation in database/dbms.hpp. Rethink ownership and lifetime of + // executioner. static Executioner executioner( (std::chrono::seconds(FLAGS_skiplist_gc_interval))); diff --git a/src/database/dbms.hpp b/src/database/dbms.hpp index acc08143a..2cf240bf0 100644 --- a/src/database/dbms.hpp +++ b/src/database/dbms.hpp @@ -15,6 +15,27 @@ DECLARE_string(snapshot_directory); DECLARE_bool(recover_on_startup); namespace fs = std::experimental::filesystem; + +// Always be sure that Dbms object is destructed before main exits, i. e. Dbms +// object shouldn't be part of global/static variable, except if its destructor +// is explicitly called before main exits. +// Consider code: +// +// Dbms dbms; // KeyIndex is created as a part of dbms. +// int main() { +// auto dba = dbms.active(); +// auto v = dba->InsertVertex(); +// v.add_label(dba->Label( +// "Start")); // New SkipList is created in KeyIndex for LabelIndex. +// // That SkipList creates SkipListGc which +// // initialises static Executioner object. +// return 0; +// } +// +// After main exits: 1. Executioner is destructed, 2. KeyIndex is destructed. +// Destructor of KeyIndex calls delete on created SkipLists which destroy +// SkipListGc that tries to use Excutioner object that doesn't exist anymore. +// -> CRASH class Dbms { public: Dbms() { diff --git a/tests/benchmark/expansion.cpp b/tests/benchmark/expansion.cpp index 495b1851f..8bb86768f 100644 --- a/tests/benchmark/expansion.cpp +++ b/tests/benchmark/expansion.cpp @@ -9,12 +9,13 @@ class ExpansionBenchFixture : public benchmark::Fixture { protected: + // Dbms shouldn't be global constructed/destructed. See documentation in + // database/dbms.hpp for details. std::experimental::optional<Dbms> dbms_; query::Interpreter interpeter_; void SetUp(const benchmark::State &state) override { - if (!dbms_) - dbms_.emplace(); + dbms_.emplace(); auto dba = dbms_->active(); for (int i = 0; i < state.range(0); i++) dba->InsertVertex(); @@ -33,22 +34,23 @@ class ExpansionBenchFixture : public benchmark::Fixture { auto dba = dbms_->active(); for (auto vertex : dba->Vertices(false)) dba->DetachRemoveVertex(vertex); dba->Commit(); + dbms_ = std::experimental::nullopt; } }; -// BENCHMARK_DEFINE_F(ExpansionBenchFixture, Match)(benchmark::State &state) { -// auto query = "MATCH (s:Start) return s"; -// auto dba = dbms_->active(); -// while (state.KeepRunning()) { -// ResultStreamFaker results; -// interpeter_.Interpret(query, *dba, results, {}); -// } -// } -// -// BENCHMARK_REGISTER_F(ExpansionBenchFixture, Match) -// ->RangeMultiplier(1024) -// ->Range(1, 1 << 20) -// ->Unit(benchmark::kMillisecond); +BENCHMARK_DEFINE_F(ExpansionBenchFixture, Match)(benchmark::State &state) { + auto query = "MATCH (s:Start) return s"; + auto dba = dbms_->active(); + while (state.KeepRunning()) { + ResultStreamFaker results; + interpeter_.Interpret(query, *dba, results, {}); + } +} + +BENCHMARK_REGISTER_F(ExpansionBenchFixture, Match) + ->RangeMultiplier(1024) + ->Range(1, 1 << 20) + ->Unit(benchmark::kMillisecond); BENCHMARK_DEFINE_F(ExpansionBenchFixture, Expand)(benchmark::State &state) { auto query = "MATCH (s:Start) WITH s MATCH (s)--(d) RETURN count(d)";