]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
test/allocator: move bluestore allocator's benchmarks to a standalone UT
authorIgor Fedotov <ifedotov@suse.com>
Fri, 4 May 2018 17:03:37 +0000 (20:03 +0300)
committerIgor Fedotov <ifedotov@suse.com>
Fri, 15 Mar 2019 14:05:03 +0000 (17:05 +0300)
Signed-off-by: Igor Fedotov <ifedotov@suse.com>
(cherry picked from commit ac2ec80cddc51f1642849c7bf226e9bed116c0d6)

src/test/objectstore/Allocator_bench.cc [new file with mode: 0755]
src/test/objectstore/Allocator_test.cc
src/test/objectstore/CMakeLists.txt

diff --git a/src/test/objectstore/Allocator_bench.cc b/src/test/objectstore/Allocator_bench.cc
new file mode 100755 (executable)
index 0000000..bdd6480
--- /dev/null
@@ -0,0 +1,340 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * In memory space allocator benchmarks.
+ * Author: Igor Fedotov, ifedotov@suse.com
+ */
+#include <iostream>
+#include <boost/scoped_ptr.hpp>
+#include <gtest/gtest.h>
+
+#include "common/Mutex.h"
+#include "common/Cond.h"
+#include "common/errno.h"
+#include "include/stringify.h"
+#include "include/Context.h"
+#include "os/bluestore/Allocator.h"
+
+#include <boost/random/uniform_int.hpp>
+typedef boost::mt11213b gen_type;
+
+#include "common/debug.h"
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_
+
+#if GTEST_HAS_PARAM_TEST
+
+class AllocTest : public ::testing::TestWithParam<const char*> {
+
+public:
+  boost::scoped_ptr<Allocator> alloc;
+  AllocTest(): alloc(0) { }
+  void init_alloc(int64_t size, uint64_t min_alloc_size) {
+    std::cout << "Creating alloc type " << string(GetParam()) << " \n";
+    alloc.reset(Allocator::create(g_ceph_context, string(GetParam()), size,
+                                 min_alloc_size));
+  }
+
+  void init_close() {
+    alloc.reset(0);
+  }
+  void doOverwriteTest(uint64_t capacity, uint64_t prefill,
+    uint64_t overwrite);
+};
+
+const uint64_t _1m = 1024 * 1024;
+const uint64_t _2m = 2 * 1024 * 1024;
+
+void dump_mempools()
+{
+  ostringstream ostr;
+  Formatter* f = Formatter::create("json-pretty", "json-pretty", "json-pretty");
+  ostr << "Mempools: ";
+  f->open_object_section("mempools");
+  mempool::dump(f);
+  f->close_section();
+  f->flush(ostr);
+  delete f;
+  ldout(g_ceph_context, 0) << ostr.str() << dendl;
+}
+
+class AllocTracker
+{
+  std::vector<uint64_t> allocations;
+  uint64_t head = 0;
+  uint64_t tail = 0;
+  uint64_t size = 0;
+  boost::uniform_int<> u1;
+
+public:
+  AllocTracker(uint64_t capacity, uint64_t alloc_unit)
+    : u1(capacity, alloc_unit)
+  {
+    assert(alloc_unit >= 0x100);
+    assert(capacity <= (uint64_t(1) << 48)); // we use 5 octets (bytes 1 - 5) to store
+                                // offset to save the required space.
+                                // This supports capacity up to 281 TB
+
+    allocations.resize(capacity / alloc_unit);
+  }
+  inline uint64_t get_head() const
+  {
+    return head;
+  }
+
+  inline uint64_t get_tail() const
+  {
+    return tail;
+  }
+
+  bool push(uint64_t offs, uint32_t len)
+  {
+    assert((len & 0xff) == 0);
+    assert((offs & 0xff) == 0);
+    assert((offs & 0xffff000000000000) == 0);
+
+    if (head + 1 == tail)
+      return false;
+    uint64_t val = (offs << 16) | (len >> 8);
+    allocations[head++] = val;
+    head %= allocations.size();
+    ++size;
+    return true;
+  }
+  bool pop(uint64_t* offs, uint32_t* len)
+  {
+    if (size == 0)
+      return false;
+    uint64_t val = allocations[tail++];
+    *len = uint64_t((val & 0xffffff) << 8);
+    *offs = (val >> 16) & ~uint64_t(0xff);
+    tail %= allocations.size();
+    --size;
+    return true;
+  }
+  bool pop_random(gen_type& rng, uint64_t* offs, uint32_t* len,
+    uint32_t max_len = 0)
+  {
+    if (size == 0)
+      return false;
+
+    uint64_t pos = (u1(rng) % size) + tail;
+    pos %= allocations.size();
+    uint64_t val = allocations[pos];
+    *len = uint64_t((val & 0xffffff) << 8);
+    *offs = (val >> 16) & ~uint64_t(0xff);
+    if (max_len && *len > max_len) {
+      val = ((*offs + max_len) << 16) | ((*len - max_len) >> 8);
+      allocations[pos] = val;
+      *len = max_len;
+    } else {
+      allocations[pos] = allocations[tail++];
+      tail %= allocations.size();
+      --size;
+    }
+    return true;
+  }
+};
+
+TEST_P(AllocTest, test_alloc_bench_seq)
+{
+  uint64_t capacity = uint64_t(1024) * 1024 * 1024 * 1024;
+  uint64_t alloc_unit = 4096;
+  uint64_t want_size = alloc_unit;
+  PExtentVector allocated, tmp;
+
+  init_alloc(capacity, alloc_unit);
+  alloc->init_add_free(0, capacity);
+
+  utime_t start = ceph_clock_now();
+  for (uint64_t i = 0; i < capacity; i += want_size)
+  {
+    tmp.clear();
+    EXPECT_EQ(want_size, alloc->allocate(want_size, alloc_unit, 0, 0, &tmp));
+    if (0 == (i % (1 * 1024 * _1m))) {
+      std::cout << "alloc " << i / 1024 / 1024 << " mb of "
+        << capacity / 1024 / 1024 << std::endl;
+    }
+  }
+
+  std::cout << "releasing..." << std::endl;
+  for (size_t i = 0; i < capacity; i += want_size)
+  {
+    interval_set<uint64_t> release_set;
+    release_set.insert(i, want_size);
+    alloc->release(release_set);
+    if (0 == (i % (1 * 1024 * _1m))) {
+      std::cout << "release " << i / 1024 / 1024 << " mb of "
+        << capacity / 1024 / 1024 << std::endl;
+    }
+  }
+  std::cout<<"Executed in "<< ceph_clock_now() - start << std::endl;
+  dump_mempools();
+}
+
+TEST_P(AllocTest, test_alloc_bench)
+{
+  uint64_t capacity = uint64_t(1024) * 1024 * 1024 * 1024;
+  uint64_t alloc_unit = 4096;
+  PExtentVector allocated, tmp;
+  AllocTracker at(capacity, alloc_unit);
+
+  init_alloc(capacity, alloc_unit);
+  alloc->init_add_free(0, capacity);
+
+  gen_type rng(time(NULL));
+  boost::uniform_int<> u1(0, 9); // 4K-2M
+  boost::uniform_int<> u2(0, 7); // 4K-512K
+
+  utime_t start = ceph_clock_now();
+  for (uint64_t i = 0; i < capacity * 2; )
+  {
+    uint32_t want = alloc_unit << u1(rng);
+
+    tmp.clear();
+    auto r = alloc->allocate(want, alloc_unit, 0, 0, &tmp);
+    if (r < want) {
+      break;
+    }
+    i += r;
+
+    for(auto a : tmp) {
+      bool full = !at.push(a.offset, a.length);
+      EXPECT_EQ(full, false);
+    }
+    uint64_t want_release = alloc_unit << u2(rng);
+    uint64_t released = 0;
+    do {
+      uint64_t o = 0;
+      uint32_t l = 0;
+      interval_set<uint64_t> release_set;
+      if (!at.pop_random(rng, &o, &l, want_release - released)) {
+       break;
+      }
+      release_set.insert(o, l);
+      alloc->release(release_set);
+      released += l;
+    } while (released < want_release);
+
+    if (0 == (i % (1 * 1024 * _1m))) {
+      std::cout << "alloc " << i / 1024 / 1024 << " mb of "
+        << capacity / 1024 / 1024 << std::endl;
+    }
+  }
+  std::cout<<"Executed in "<< ceph_clock_now() - start << std::endl;
+  std::cout<<"Avail "<< alloc->get_free() / _1m << " MB" << std::endl;
+  dump_mempools();
+}
+
+void AllocTest::doOverwriteTest(uint64_t capacity, uint64_t prefill,
+  uint64_t overwrite)
+{
+  uint64_t alloc_unit = 4096;
+  PExtentVector allocated, tmp;
+  AllocTracker at(capacity, alloc_unit);
+
+  init_alloc(capacity, alloc_unit);
+  alloc->init_add_free(0, capacity);
+
+  gen_type rng(time(NULL));
+  boost::uniform_int<> u1(0, 9); // 4K-2M
+  boost::uniform_int<> u2(0, 9); // 4K-512K
+
+  utime_t start = ceph_clock_now();
+  // allocate 90% of the capacity
+  auto cap = prefill;
+  for (uint64_t i = 0; i < cap; )
+  {
+    uint32_t want = alloc_unit << u1(rng);
+    tmp.clear();
+    auto r = alloc->allocate(want, alloc_unit, 0, 0, &tmp);
+    if (r < want) {
+      break;
+    }
+    i += r;
+
+    for(auto a : tmp) {
+      bool full = !at.push(a.offset, a.length);
+      EXPECT_EQ(full, false);
+    }
+    if (0 == (i % (1 * 1024 * _1m))) {
+      std::cout << "alloc " << i / 1024 / 1024 << " mb of "
+        << cap / 1024 / 1024 << std::endl;
+    }
+  }
+
+  cap = overwrite;
+  for (uint64_t i = 0; i < cap; )
+  {
+    uint64_t want_release = alloc_unit << u2(rng);
+    uint64_t released = 0;
+    do {
+      uint64_t o = 0;
+      uint32_t l = 0;
+      interval_set<uint64_t> release_set;
+      if (!at.pop_random(rng, &o, &l, want_release - released)) {
+       break;
+      }
+      release_set.insert(o, l);
+      alloc->release(release_set);
+      released += l;
+    } while (released < want_release);
+
+    uint32_t want = alloc_unit << u1(rng);
+    tmp.clear();
+    auto r = alloc->allocate(want, alloc_unit, 0, 0, &tmp);
+    if (r != want) {
+      std::cout<<"Can't allocate more space, stopping."<< std::endl;
+      break;
+    }
+    i += r;
+
+    for(auto a : tmp) {
+      bool full = !at.push(a.offset, a.length);
+      EXPECT_EQ(full, false);
+    }
+
+    if (0 == (i % (1 * 1024 * _1m))) {
+      std::cout << "reuse " << i / 1024 / 1024 << " mb of "
+        << cap / 1024 / 1024 << std::endl;
+    }
+  }
+  std::cout<<"Executed in "<< ceph_clock_now() - start << std::endl;
+  std::cout<<"Avail "<< alloc->get_free() / _1m << " MB" << std::endl;
+
+  dump_mempools();
+}
+
+TEST_P(AllocTest, test_alloc_bench_90_300)
+{
+  uint64_t capacity = uint64_t(1024) * 1024 * 1024 * 1024;
+  auto prefill = capacity - capacity / 10;
+  auto overwrite = capacity * 3;
+  doOverwriteTest(capacity, prefill, overwrite);
+}
+
+TEST_P(AllocTest, test_alloc_bench_50_300)
+{
+  uint64_t capacity = uint64_t(1024) * 1024 * 1024 * 1024;
+  auto prefill = capacity / 2;
+  auto overwrite = capacity * 3;
+  doOverwriteTest(capacity, prefill, overwrite);
+}
+
+TEST_P(AllocTest, test_alloc_bench_10_300)
+{
+  uint64_t capacity = uint64_t(1024) * 1024 * 1024 * 1024;
+  auto prefill = capacity / 10;
+  auto overwrite = capacity * 3;
+  doOverwriteTest(capacity, prefill, overwrite);
+}
+
+INSTANTIATE_TEST_CASE_P(
+  Allocator,
+  AllocTest,
+  ::testing::Values("stupid", "bitmap"));
+
+#else
+
+TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}
+#endif
index 3e4f0bb095afda867e9151c5208f18ff40d4e285..5ff3aad7c59eaec1e879ffe19b643a16adff92b5 100644 (file)
@@ -21,18 +21,19 @@ typedef boost::mt11213b gen_type;
 #if GTEST_HAS_PARAM_TEST
 
 class AllocTest : public ::testing::TestWithParam<const char*> {
+
 public:
-    boost::scoped_ptr<Allocator> alloc;
-    AllocTest(): alloc(0) { }
-    void init_alloc(int64_t size, uint64_t min_alloc_size) {
-      std::cout << "Creating alloc type " << string(GetParam()) << " \n";
-      alloc.reset(Allocator::create(g_ceph_context, string(GetParam()), size,
-                                   min_alloc_size));
-    }
+  boost::scoped_ptr<Allocator> alloc;
+  AllocTest(): alloc(0) { }
+  void init_alloc(int64_t size, uint64_t min_alloc_size) {
+    std::cout << "Creating alloc type " << string(GetParam()) << " \n";
+    alloc.reset(Allocator::create(g_ceph_context, string(GetParam()), size,
+                                 min_alloc_size));
+  }
 
-    void init_close() {
-      alloc.reset(0);
-    }
+  void init_close() {
+    alloc.reset(0);
+  }
 };
 
 TEST_P(AllocTest, test_alloc_init)
@@ -276,174 +277,6 @@ TEST_P(AllocTest, test_alloc_fragmentation)
   EXPECT_EQ(0, uint64_t(alloc->get_fragmentation(alloc_unit) * 100));
 }
 
-const uint64_t _1m = 1024 * 1024;
-const uint64_t _2m = 2 * 1024 * 1024;
-
-TEST_P(AllocTest, test_alloc_bench_seq)
-{
-  uint64_t capacity = uint64_t(1024) * 1024 * 1024 * 1024;
-  uint64_t alloc_unit = 4096;
-  uint64_t want_size = alloc_unit;
-  PExtentVector allocated, tmp;
-
-  init_alloc(capacity, alloc_unit);
-  alloc->init_add_free(0, capacity);
-
-  utime_t start = ceph_clock_now();
-  for (uint64_t i = 0; i < capacity; i += want_size)
-  {
-    tmp.clear();
-    EXPECT_EQ(want_size, alloc->allocate(want_size, alloc_unit, 0, 0, &tmp));
-    if (0 == (i % (1 * 1024 * _1m))) {
-      std::cout << "alloc " << i / 1024 / 1024 << " mb of "
-        << capacity / 1024 / 1024 << std::endl;
-    }
-  }
-
-  std::cout << "releasing..." << std::endl;
-  for (size_t i = 0; i < capacity; i += want_size)
-  {
-    interval_set<uint64_t> release_set;
-    release_set.insert(i, want_size);
-    alloc->release(release_set);
-    if (0 == (i % (1 * 1024 * _1m))) {
-      std::cout << "release " << i / 1024 / 1024 << " mb of "
-        << capacity / 1024 / 1024 << std::endl;
-    }
-  }
-  std::cout<<"Executed in "<< ceph_clock_now() - start << std::endl;
-}
-
-class AllocTracker
-{
-  std::vector<uint64_t> allocations;
-  uint64_t head = 0;
-  uint64_t tail = 0;
-  uint64_t size = 0;
-  boost::uniform_int<> u1;
-
-public:
-  AllocTracker(uint64_t capacity, uint64_t alloc_unit)
-    : u1(capacity, alloc_unit)
-  {
-    assert(alloc_unit >= 0x100);
-    assert(capacity <= (uint64_t(1) << 48)); // we use 5 octets (bytes 1 - 5) to store
-                                // offset to save the required space.
-                                // This supports capacity up to 281 TB
-
-    allocations.resize(capacity / alloc_unit);
-  }
-  inline uint64_t get_head() const
-  {
-    return head;
-  }
-
-  inline uint64_t get_tail() const
-  {
-    return tail;
-  }
-
-  bool push(uint64_t offs, uint32_t len)
-  {
-    assert((len & 0xff) == 0);
-    assert((offs & 0xff) == 0);
-    assert((offs & 0xffff000000000000) == 0);
-
-    if (head + 1 == tail)
-      return false;
-    uint64_t val = (offs << 16) | (len >> 8);
-    allocations[head++] = val;
-    head %= allocations.size();
-    ++size;
-    return true;
-  }
-  bool pop(uint64_t* offs, uint32_t* len)
-  {
-    if (size == 0)
-      return false;
-    uint64_t val = allocations[tail++];
-    *len = uint64_t((val & 0xffffff) << 8);
-    *offs = (val >> 16) & ~uint64_t(0xff);
-    tail %= allocations.size();
-    --size;
-    return true;
-  }
-  bool pop_random(gen_type& rng, uint64_t* offs, uint32_t* len,
-    uint32_t max_len = 0)
-  {
-    if (size == 0)
-      return false;
-
-    uint64_t pos = (u1(rng) % size) + tail;
-    pos %= allocations.size();
-    uint64_t val = allocations[pos];
-    *len = uint64_t((val & 0xffffff) << 8);
-    *offs = (val >> 16) & ~uint64_t(0xff);
-    if (max_len && *len > max_len) {
-      val = ((*offs + max_len) << 16) | ((*len - max_len) >> 8);
-      allocations[pos] = val;
-      *len = max_len;
-    } else {
-      allocations[pos] = allocations[tail++];
-      tail %= allocations.size();
-      --size;
-    }
-    return true;
-  }
-};
-
-TEST_P(AllocTest, test_alloc_bench)
-{
-  uint64_t capacity = uint64_t(1024) * 1024 * 1024 * 1024;
-  uint64_t alloc_unit = 4096;
-  PExtentVector allocated, tmp;
-  AllocTracker at(capacity, alloc_unit);
-
-  init_alloc(capacity, alloc_unit);
-  alloc->init_add_free(0, capacity);
-
-  gen_type rng(time(NULL));
-  boost::uniform_int<> u1(0, 9); // 4K-2M
-  boost::uniform_int<> u2(0, 7); // 4K-512K
-
-  utime_t start = ceph_clock_now();
-  for (uint64_t i = 0; i < capacity * 2; )
-  {
-    uint32_t want = alloc_unit << u1(rng);
-    auto r = alloc->allocate(want, alloc_unit, 0, 0, &tmp);
-    if (r <= 0) {
-      break;
-    }
-    i += want;
-    tmp.clear();
-
-    for(auto a : tmp) {
-      bool full = !at.push(a.offset, a.length);
-      EXPECT_EQ(full, false);
-    }
-    uint64_t want_release = alloc_unit << u2(rng);
-    uint64_t released = 0;
-    do {
-      uint64_t o = 0;
-      uint32_t l = 0;
-      interval_set<uint64_t> release_set;
-      if (!at.pop_random(rng, &o, &l, want_release - released)) {
-       break;
-      }
-      release_set.insert(o, l);
-      alloc->release(release_set);
-      released += l;
-    } while (released < want_release);
-
-    if (0 == (i % (1 * 1024 * _1m))) {
-      std::cout << "alloc " << i / 1024 / 1024 << " mb of "
-        << capacity / 1024 / 1024 << std::endl;
-    }
-  }
-  std::cout<<"Executed in "<< ceph_clock_now() - start << std::endl;
-  std::cout<<"Avail "<< alloc->get_free() / _1m << " MB" << std::endl;
-}
-
 INSTANTIATE_TEST_CASE_P(
   Allocator,
   AllocTest,
index e2666870a703a2b86d6fe76b97faf9790cf3a8a7..cf2fb8a4f0abeaa2850659f78f754bb0784acaa7 100644 (file)
@@ -111,6 +111,14 @@ if(WITH_BLUESTORE)
   add_ceph_unittest(unittest_alloc)
   target_link_libraries(unittest_alloc os global)
 
+
+  add_executable(unittest_alloc_bench
+    Allocator_bench.cc
+    $<TARGET_OBJECTS:unit-main>
+    )
+  add_ceph_unittest(unittest_alloc_bench)
+  target_link_libraries(unittest_alloc_bench os global)
+
   add_executable(unittest_fastbmap_allocator
     fastbmap_allocator_test.cc
     $<TARGET_OBJECTS:unit-main>