[Groonga-commit] groonga/grnxx at a32d5e7 [master] Implement grnxx::map::Pool::defrag().

Back to archive index

susumu.yata null+****@clear*****
Fri Aug 16 18:19:36 JST 2013


susumu.yata	2013-08-16 18:19:36 +0900 (Fri, 16 Aug 2013)

  New Revision: a32d5e763d0adfb3532bfcf41c75545a86fc6555
  https://github.com/groonga/grnxx/commit/a32d5e763d0adfb3532bfcf41c75545a86fc6555

  Message:
    Implement grnxx::map::Pool::defrag().

  Modified files:
    lib/grnxx/map/pool.cpp
    lib/grnxx/map/pool.hpp

  Modified: lib/grnxx/map/pool.cpp (+47 -1)
===================================================================
--- lib/grnxx/map/pool.cpp    2013-08-16 17:24:20 +0900 (6157cdd)
+++ lib/grnxx/map/pool.cpp    2013-08-16 18:19:36 +0900 (e92b07a)
@@ -180,6 +180,7 @@ int64_t Pool<T>::add(KeyArg key) {
 
 template <typename T>
 void Pool<T>::defrag() {
+  refresh_if_possible();
   // Nothing to do.
 }
 
@@ -502,7 +503,52 @@ int64_t Pool<Bytes>::add(KeyArg key) {
 
 void Pool<Bytes>::defrag() {
   index_pool_->defrag();
-  // TODO
+  refresh_if_possible();
+  if (header_->size <= PAGE_SIZE) {
+    // Nothing to do.
+    return;
+  }
+  // Keys in the active page should not be moved.
+  const uint64_t offset_threshold =
+      header_->next_offset - (header_->next_offset % PAGE_SIZE);
+  // Keys in low-usage-rate pages should be moved.
+  const uint32_t size_in_use_threshold =
+      static_cast<uint32_t>(PAGE_SIZE * USAGE_RATE_THRESHOLD);
+  const int64_t max_key_id = index_pool_->max_key_id();
+  uint32_t prev_page_id = INVALID_PAGE_ID;
+  uint8_t *page = nullptr;
+  for (int64_t key_id = MIN_KEY_ID; key_id <= max_key_id; ++key_id) {
+    // TODO: "index_pool_->get/reset()" can be the bottleneck.
+    uint64_t bytes_id;
+    if (!index_pool_->get(key_id, &bytes_id)) {
+      continue;
+    }
+    const uint64_t offset = get_offset(bytes_id);
+    if (offset >= offset_threshold) {
+      continue;
+    }
+    const uint32_t page_id = static_cast<uint32_t>(offset / PAGE_SIZE);
+    if (page_id != prev_page_id) {
+      if (table_[page_id].size_in_use >= size_in_use_threshold) {
+        page = nullptr;
+      } else {
+        page = get_page(page_id);
+      }
+      prev_page_id = page_id;
+    }
+    if (!page) {
+      continue;
+    }
+    const uint32_t bytes_size = get_size(bytes_id);
+    const Bytes bytes(page + (offset % PAGE_SIZE), bytes_size);
+    const uint64_t new_bytes_id = add_bytes(bytes);
+    index_pool_->reset(key_id, new_bytes_id);
+    table_[page_id].size_in_use -= bytes_size;
+    if (table_[page_id].size_in_use == 0) {
+      // Unlink a page if this operation makes it empty.
+      storage_->unlink_node(table_[page_id].page_storage_node_id);
+    }
+  }
 }
 
 void Pool<Bytes>::sweep(Duration lifetime) {

  Modified: lib/grnxx/map/pool.hpp (+2 -0)
===================================================================
--- lib/grnxx/map/pool.hpp    2013-08-16 17:24:20 +0900 (3d628ad)
+++ lib/grnxx/map/pool.hpp    2013-08-16 18:19:36 +0900 (101bc76)
@@ -211,6 +211,8 @@ class Pool<Bytes> {
 
   static constexpr uint64_t EMPTY_BYTES_ID = 0;
 
+  static constexpr double   USAGE_RATE_THRESHOLD = 0.5;
+
  public:
   using Key = typename Traits<Bytes>::Type;
   using KeyArg = typename Traits<Bytes>::ArgumentType;
-------------- next part --------------
HTML����������������������������...
Descargar 



More information about the Groonga-commit mailing list
Back to archive index