Move defragmenter benchmarks to benchmarks 76/76476/5
authorolivermd <oliver.downard@couchbase.com>
Fri, 7 Apr 2017 14:01:11 +0000 (15:01 +0100)
committerDave Rigby <daver@couchbase.com>
Tue, 11 Apr 2017 09:44:28 +0000 (09:44 +0000)
This moves the defragmenter benchmarks to ep_engine_benchmarks because
they can take ~18 seconds under ASAN. It also makes sense to group all
the benchmarks together.

To enable this move, this commit also puts the defragmenter test in to a
header file so that it can continued to be used by the defragmenter
tests which are not benchmarks.

Change-Id: I69f8da02c07e6469b9c80fbe06507c80d866ac7f
Reviewed-on: http://review.couchbase.org/76476
Reviewed-by: Dave Rigby <daver@couchbase.com>
Tested-by: Build Bot <build@couchbase.com>
CMakeLists.txt
benchmarks/access_scanner_bench.cc
benchmarks/defragmenter_bench.cc [new file with mode: 0644]
tests/module_tests/defragmenter_test.cc
tests/module_tests/defragmenter_test.h [new file with mode: 0644]

index 756de1c..c9243a3 100644 (file)
@@ -330,7 +330,9 @@ ADD_EXECUTABLE(ep_engine_benchmarks
                ${Memcached_SOURCE_DIR}/daemon/doc_pre_expiry.cc
                ${Memcached_SOURCE_DIR}/daemon/protocol/mcbp/engine_errc_2_mcbp.cc
                ${Memcached_SOURCE_DIR}/utilities/string_utilities.cc
-               benchmarks/benchmark_memory_tracker.cc)
+               benchmarks/benchmark_memory_tracker.cc
+               benchmarks/defragmenter_bench.cc
+               tests/module_tests/vbucket_test.cc)
 
 TARGET_LINK_LIBRARIES(ep_engine_benchmarks benchmark platform xattr couchstore
         cJSON dirutils engine_utilities gtest gmock JSON_checker mcd_util
index 8575f79..ca6cd76 100644 (file)
@@ -173,4 +173,6 @@ int main(int argc, char** argv) {
     initialize_time_functions(get_mock_server_api()->core);
     ::benchmark::Initialize(&argc, argv);
     ::benchmark::RunSpecifiedBenchmarks();
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
 }
diff --git a/benchmarks/defragmenter_bench.cc b/benchmarks/defragmenter_bench.cc
new file mode 100644 (file)
index 0000000..99c0ab7
--- /dev/null
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ *     Copyright 2017 Couchbase, Inc
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+
+#include "defragmenter_visitor.h"
+#include "tests/module_tests/defragmenter_test.h"
+#include "tests/module_tests/test_helpers.h"
+
+#include <gtest/gtest.h>
+#include <valgrind/valgrind.h>
+
+
+/* Measure the rate at which the defragmenter can defragment documents, using
+ * the given age threshold.
+ *
+ * Setup a Defragmenter, then time how long it takes to visit them all
+ * documents in the given vbucket, npasses times.
+ */
+static size_t benchmarkDefragment(VBucket& vbucket, size_t passes,
+                                  uint8_t age_threshold,
+                                  size_t chunk_duration_ms) {
+    // Create and run visitor for the specified number of iterations, with
+    // the given age.
+    DefragmentVisitor visitor(age_threshold);
+    hrtime_t start = gethrtime();
+    for (size_t i = 0; i < passes; i++) {
+        // Loop until we get to the end; this may take multiple chunks depending
+        // on the chunk_duration.
+        HashTable::Position pos;
+        while (pos != vbucket.ht.endPosition()) {
+            visitor.setDeadline(gethrtime() +
+                                (chunk_duration_ms * 1000 * 1000));
+            pos = vbucket.ht.pauseResumeVisit(visitor, pos);
+        }
+    }
+    hrtime_t end = gethrtime();
+    size_t visited = visitor.getVisitedCount();
+
+    double duration_s = (end - start) / double(1000 * 1000 * 1000);
+    return size_t(visited / duration_s);
+}
+
+
+class DefragmenterBenchmarkTest : public DefragmenterTest {
+protected:
+    /* Fill the bucket with the given number of docs. Returns the rate at which
+     * items were added.
+     */
+    size_t populateVbucket() {
+        // How many items to create in the VBucket. Use a large number for
+        // normal runs when measuring performance, but a very small number
+        // (enough for functional testing) when running under Valgrind
+        // where there's no sense in measuring performance.
+        const size_t ndocs = RUNNING_ON_VALGRIND ? 10 : 500000;
+
+        /* Set the hashTable to a sensible size */
+        vbucket->ht.resize(ndocs);
+
+        /* Store items */
+        char value[256];
+        hrtime_t start = gethrtime();
+        for (size_t i = 0; i < ndocs; i++) {
+            std::string key = "key" + std::to_string(i);
+            Item item(makeStoredDocKey(key), 0, 0, value, sizeof(value));
+            public_processSet(item, 0);
+        }
+        hrtime_t end = gethrtime();
+
+        // Let hashTable set itself to correct size, post-fill
+        vbucket->ht.resize();
+
+        double duration_s = (end - start) / double(1000 * 1000 * 1000);
+        return size_t(ndocs / duration_s);
+    }
+
+};
+
+TEST_P(DefragmenterBenchmarkTest, Populate) {
+    size_t populateRate = populateVbucket();
+    RecordProperty("items_per_sec", populateRate);
+}
+
+TEST_P(DefragmenterBenchmarkTest, Visit) {
+    populateVbucket();
+    const size_t one_minute = 60 * 1000;
+    size_t visit_rate = benchmarkDefragment(*vbucket, 1,
+                                            std::numeric_limits<uint8_t>::max(),
+                                            one_minute);
+    RecordProperty("items_per_sec", visit_rate);
+}
+
+TEST_P(DefragmenterBenchmarkTest, DefragAlways) {
+    populateVbucket();
+    const size_t one_minute = 60 * 1000;
+    size_t defrag_always_rate = benchmarkDefragment(*vbucket, 1, 0,
+                                                    one_minute);
+    RecordProperty("items_per_sec", defrag_always_rate);
+}
+
+TEST_P(DefragmenterBenchmarkTest, DefragAge10) {
+    populateVbucket();
+    const size_t one_minute = 60 * 1000;
+    size_t defrag_age10_rate = benchmarkDefragment(*vbucket, 1, 10,
+                                                   one_minute);
+    RecordProperty("items_per_sec", defrag_age10_rate);
+}
+
+TEST_P(DefragmenterBenchmarkTest, DefragAge10_20ms) {
+    populateVbucket();
+    size_t defrag_age10_20ms_rate = benchmarkDefragment(*vbucket, 1, 10, 20);
+    RecordProperty("items_per_sec", defrag_age10_20ms_rate);
+}
+
+INSTANTIATE_TEST_CASE_P(
+        FullAndValueEviction,
+        DefragmenterBenchmarkTest,
+        ::testing::Values(VALUE_ONLY, FULL_EVICTION),
+        [](const ::testing::TestParamInfo<item_eviction_policy_t>& info) {
+            if (info.param == VALUE_ONLY) {
+                return "VALUE_ONLY";
+            } else {
+                return "FULL_EVICTION";
+            }
+        });
index aa4443b..0b7c3ca 100644 (file)
  *   limitations under the License.
  */
 
-#include "defragmenter_visitor.h"
+#include "defragmenter_test.h"
 
 #include "daemon/alloc_hooks.h"
-#include "programs/engine_testapp/mock_server.h"
-#include "tests/module_tests/test_helpers.h"
-#include "vbucket_test.h"
+#include "defragmenter_visitor.h"
 
 #include <gtest/gtest.h>
-#include <iomanip>
-#include <locale>
-#include <platform/cb_malloc.h>
 #include <valgrind/valgrind.h>
 
 
-/* Measure the rate at which the defragmenter can defragment documents, using
- * the given age threshold.
- *
- * Setup a Defragmenter, then time how long it takes to visit them all
- * documents in the given vbucket, npasses times.
- */
-static size_t benchmarkDefragment(VBucket& vbucket, size_t passes,
-                                  uint8_t age_threshold,
-                                  size_t chunk_duration_ms) {
-    // Create and run visitor for the specified number of iterations, with
-    // the given age.
-    DefragmentVisitor visitor(age_threshold);
-    hrtime_t start = gethrtime();
-    for (size_t i = 0; i < passes; i++) {
-        // Loop until we get to the end; this may take multiple chunks depending
-        // on the chunk_duration.
-        HashTable::Position pos;
-        while (pos != vbucket.ht.endPosition()) {
-            visitor.setDeadline(gethrtime() +
-                                 (chunk_duration_ms * 1000 * 1000));
-            pos = vbucket.ht.pauseResumeVisit(visitor, pos);
-        }
-    }
-    hrtime_t end = gethrtime();
-    size_t visited = visitor.getVisitedCount();
-
-    double duration_s = (end - start) / double(1000 * 1000 * 1000);
-    return size_t(visited / duration_s);
-}
-
-class DefragmenterTest : public VBucketTest {
-public:
-    static void SetUpTestCase() {
-
-        // Setup the MemoryTracker.
-        MemoryTracker::getInstance(*get_mock_server_api()->alloc_hooks);
-    }
-
-    static void TearDownTestCase() {
-        MemoryTracker::destroyInstance();
-    }
-
-protected:
-    void SetUp() override {
-        // Setup object registry. As we do not create a full ep-engine, we
-        // use the "initial_tracking" for all memory tracking".
-        ObjectRegistry::setStats(&mem_used);
-        VBucketTest::SetUp();
-    }
-
-    void TearDown() override {
-        ObjectRegistry::setStats(nullptr);
-        VBucketTest::TearDown();
-    }
-
-    // Track of memory used (from ObjectRegistry).
-    std::atomic<size_t> mem_used{0};
-};
-
-
-class DefragmenterBenchmarkTest : public DefragmenterTest {
-protected:
-    /* Fill the bucket with the given number of docs. Returns the rate at which
-     * items were added.
-     */
-    size_t populateVbucket() {
-        // How many items to create in the VBucket. Use a large number for
-        // normal runs when measuring performance, but a very small number
-        // (enough for functional testing) when running under Valgrind
-        // where there's no sense in measuring performance.
-        const size_t ndocs = RUNNING_ON_VALGRIND ? 10 : 500000;
-
-        /* Set the hashTable to a sensible size */
-        vbucket->ht.resize(ndocs);
-
-        /* Store items */
-        char value[256];
-        hrtime_t start = gethrtime();
-        for (size_t i = 0; i < ndocs; i++) {
-            std::string key = "key" + std::to_string(i);
-            Item item(makeStoredDocKey(key), 0, 0, value, sizeof(value));
-            public_processSet(item, 0);
-        }
-        hrtime_t end = gethrtime();
-
-        // Let hashTable set itself to correct size, post-fill
-        vbucket->ht.resize();
-
-        double duration_s = (end - start) / double(1000 * 1000 * 1000);
-        return size_t(ndocs / duration_s);
-    }
-
-};
-
-TEST_P(DefragmenterBenchmarkTest, Populate) {
-    size_t populateRate = populateVbucket();
-    RecordProperty("items_per_sec", populateRate);
-}
-
-TEST_P(DefragmenterBenchmarkTest, Visit) {
-    populateVbucket();
-    const size_t one_minute = 60 * 1000;
-    size_t visit_rate = benchmarkDefragment(*vbucket, 1,
-                                            std::numeric_limits<uint8_t>::max(),
-                                            one_minute);
-    RecordProperty("items_per_sec", visit_rate);
-}
-
-TEST_P(DefragmenterBenchmarkTest, DefragAlways) {
-    populateVbucket();
-    const size_t one_minute = 60 * 1000;
-    size_t defrag_always_rate = benchmarkDefragment(*vbucket, 1, 0,
-                                                    one_minute);
-    RecordProperty("items_per_sec", defrag_always_rate);
-}
-
-TEST_P(DefragmenterBenchmarkTest, DefragAge10) {
-    populateVbucket();
-    const size_t one_minute = 60 * 1000;
-    size_t defrag_age10_rate = benchmarkDefragment(*vbucket, 1, 10,
-                                                   one_minute);
-    RecordProperty("items_per_sec", defrag_age10_rate);
-}
-
-TEST_P(DefragmenterBenchmarkTest, DefragAge10_20ms) {
-    populateVbucket();
-    size_t defrag_age10_20ms_rate = benchmarkDefragment(*vbucket, 1, 10, 20);
-    RecordProperty("items_per_sec", defrag_age10_20ms_rate);
-}
-
-INSTANTIATE_TEST_CASE_P(
-        FullAndValueEviction,
-        DefragmenterBenchmarkTest,
-        ::testing::Values(VALUE_ONLY, FULL_EVICTION),
-        [](const ::testing::TestParamInfo<item_eviction_policy_t>& info) {
-            if (info.param == VALUE_ONLY) {
-                return "VALUE_ONLY";
-            } else {
-                return "FULL_EVICTION";
-            }
-        });
-
 /* Return how many bytes the memory allocator has mapped in RAM - essentially
  * application-allocated bytes plus memory in allocators own data structures
  * & freelists. This is an approximation of the the application's RSS.
diff --git a/tests/module_tests/defragmenter_test.h b/tests/module_tests/defragmenter_test.h
new file mode 100644 (file)
index 0000000..bcbcb23
--- /dev/null
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ *     Copyright 2017 Couchbase, Inc
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+
+#pragma once
+
+#include "vbucket_test.h"
+
+#include <programs/engine_testapp/mock_server.h>
+
+class DefragmenterTest : public VBucketTest {
+public:
+    static void SetUpTestCase() {
+
+        // Setup the MemoryTracker.
+        MemoryTracker::getInstance(*get_mock_server_api()->alloc_hooks);
+    }
+
+    static void TearDownTestCase() {
+        MemoryTracker::destroyInstance();
+    }
+
+protected:
+    void SetUp() override {
+        // Setup object registry. As we do not create a full ep-engine, we
+        // use the "initial_tracking" for all memory tracking".
+        ObjectRegistry::setStats(&mem_used);
+        VBucketTest::SetUp();
+    }
+
+    void TearDown() override {
+        ObjectRegistry::setStats(nullptr);
+        VBucketTest::TearDown();
+    }
+
+    // Track of memory used (from ObjectRegistry).
+    std::atomic<size_t> mem_used{0};
+};