]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/os/seastore/cache: count transactional cache access/hit
authorYingxin Cheng <yingxin.cheng@intel.com>
Fri, 9 Jul 2021 07:09:55 +0000 (15:09 +0800)
committerYingxin Cheng <yingxin.cheng@intel.com>
Tue, 20 Jul 2021 08:19:35 +0000 (16:19 +0800)
Labeled by source and extent-type.

Signed-off-by: Yingxin Cheng <yingxin.cheng@intel.com>
src/crimson/os/seastore/cache.cc
src/crimson/os/seastore/cache.h
src/crimson/os/seastore/transaction_manager.cc

index f0929fd276c3988f1e66d0a7790f1f70ed49f833..565f6fa8489c114bbb5f092a9cc701840637ca72 100644 (file)
@@ -46,7 +46,8 @@ Cache::retire_extent_ret Cache::retire_extent_addr(
   }
 
   // absent from transaction
-  ext = query_cache(addr);
+  // retiring is not included by the cache hit metrics
+  ext = query_cache(addr, nullptr);
   if (ext) {
     if (ext->get_type() != extent_types_t::RETIRED_PLACEHOLDER) {
       t.add_to_read_set(ext);
@@ -245,6 +246,76 @@ void Cache::register_metrics()
       ),
     }
   );
+
+  /*
+   * cache_query: cache_access and cache_hit
+   */
+  auto register_cache_access =
+    [this, &labels_by_src, &labels_by_ext]
+    (src_t src, const sm::label_instance& src_label,
+     extent_types_t ext, const sm::label_instance& ext_label) {
+      auto m_key = std::make_pair(src, ext);
+      stats.cache_query[m_key] = {0, 0};
+      {
+        metrics.add_group(
+          "cache",
+          {
+            sm::make_counter(
+              "cache_access",
+              stats.cache_query.find(m_key)->second.access,
+              sm::description("total number of cache accesses labeled by "
+                              "transaction source and extent type"),
+              {src_label, ext_label}
+            ),
+            sm::make_counter(
+              "cache_hit",
+              stats.cache_query.find(m_key)->second.hit,
+              sm::description("total number of cache hits labeled by "
+                              "transaction source and extent type"),
+              {src_label, ext_label}
+            ),
+          }
+        );
+      }
+    };
+
+  for (auto& [src, src_label] : labels_by_src) {
+    for (auto& [ext, ext_label] : labels_by_ext) {
+      if (ext != extent_types_t::RETIRED_PLACEHOLDER) {
+        register_cache_access(src, src_label, ext, ext_label);
+      }
+    }
+  }
+
+  metrics.add_group(
+    "cache",
+    {
+      sm::make_counter(
+        "cache_access",
+        [this] {
+          uint64_t total = 0;
+          for (auto& [k, v] : stats.cache_query) {
+            total += v.access;
+          }
+          return total;
+        },
+        sm::description("total number of cache accesses"),
+        {src_label("ALL")}
+      ),
+      sm::make_counter(
+        "cache_hit",
+        [this] {
+          uint64_t total = 0;
+          for (auto& [k, v] : stats.cache_query) {
+            total += v.hit;
+          }
+          return total;
+        },
+        sm::description("total number of cache hits"),
+        {src_label("ALL")}
+      ),
+    }
+  );
 }
 
 void Cache::add_extent(CachedExtentRef ref)
@@ -649,7 +720,8 @@ Cache::replay_delta(
   } else {
     auto _get_extent_if_cached = [this](paddr_t addr)
       -> get_extent_ertr::future<CachedExtentRef> {
-      auto ret = query_cache(addr);
+      // replay is not included by the cache hit metrics
+      auto ret = query_cache(addr, nullptr);
       if (ret) {
         // no retired-placeholder should be exist yet because no transaction
         // has been created.
@@ -662,11 +734,13 @@ Cache::replay_delta(
       }
     };
     auto extent_fut = (delta.pversion == 0 ?
+      // replay is not included by the cache hit metrics
       get_extent_by_type(
-       delta.type,
-       delta.paddr,
-       delta.laddr,
-       delta.length) :
+        delta.type,
+        delta.paddr,
+        delta.laddr,
+        delta.length,
+        nullptr) :
       _get_extent_if_cached(
        delta.paddr)
     ).handle_error(
@@ -764,45 +838,60 @@ Cache::get_extent_ertr::future<CachedExtentRef> Cache::get_extent_by_type(
   extent_types_t type,
   paddr_t offset,
   laddr_t laddr,
-  segment_off_t length)
+  segment_off_t length,
+  const Transaction::src_t* p_src)
 {
   return [=] {
+    src_ext_t* p_metric_key = nullptr;
+    src_ext_t metric_key;
+    if (p_src) {
+      metric_key = std::make_pair(*p_src, type);
+      p_metric_key = &metric_key;
+    }
+
     switch (type) {
     case extent_types_t::ROOT:
       assert(0 == "ROOT is never directly read");
       return get_extent_ertr::make_ready_future<CachedExtentRef>();
     case extent_types_t::LADDR_INTERNAL:
-      return get_extent<lba_manager::btree::LBAInternalNode>(offset, length
+      return get_extent<lba_manager::btree::LBAInternalNode>(
+          offset, length, p_metric_key
       ).safe_then([](auto extent) {
        return CachedExtentRef(extent.detach(), false /* add_ref */);
       });
     case extent_types_t::LADDR_LEAF:
-      return get_extent<lba_manager::btree::LBALeafNode>(offset, length
+      return get_extent<lba_manager::btree::LBALeafNode>(
+          offset, length, p_metric_key
       ).safe_then([](auto extent) {
        return CachedExtentRef(extent.detach(), false /* add_ref */);
       });
     case extent_types_t::OMAP_INNER:
-      return get_extent<omap_manager::OMapInnerNode>(offset, length
+      return get_extent<omap_manager::OMapInnerNode>(
+          offset, length, p_metric_key
       ).safe_then([](auto extent) {
         return CachedExtentRef(extent.detach(), false /* add_ref */);
       });
     case extent_types_t::OMAP_LEAF:
-      return get_extent<omap_manager::OMapLeafNode>(offset, length
+      return get_extent<omap_manager::OMapLeafNode>(
+          offset, length, p_metric_key
       ).safe_then([](auto extent) {
         return CachedExtentRef(extent.detach(), false /* add_ref */);
       });
     case extent_types_t::COLL_BLOCK:
-      return get_extent<collection_manager::CollectionNode>(offset, length
+      return get_extent<collection_manager::CollectionNode>(
+          offset, length, p_metric_key
       ).safe_then([](auto extent) {
         return CachedExtentRef(extent.detach(), false /* add_ref */);
       });
     case extent_types_t::ONODE_BLOCK_STAGED:
-      return get_extent<onode::SeastoreNodeExtent>(offset, length
+      return get_extent<onode::SeastoreNodeExtent>(
+          offset, length, p_metric_key
       ).safe_then([](auto extent) {
        return CachedExtentRef(extent.detach(), false /* add_ref */);
       });
     case extent_types_t::OBJECT_DATA_BLOCK:
-      return get_extent<ObjectDataBlock>(offset, length
+      return get_extent<ObjectDataBlock>(
+          offset, length, p_metric_key
       ).safe_then([](auto extent) {
        return CachedExtentRef(extent.detach(), false /* add_ref */);
       });
@@ -810,12 +899,14 @@ Cache::get_extent_ertr::future<CachedExtentRef> Cache::get_extent_by_type(
       ceph_assert(0 == "impossible");
       return get_extent_ertr::make_ready_future<CachedExtentRef>();
     case extent_types_t::TEST_BLOCK:
-      return get_extent<TestBlock>(offset, length
+      return get_extent<TestBlock>(
+          offset, length, p_metric_key
       ).safe_then([](auto extent) {
        return CachedExtentRef(extent.detach(), false /* add_ref */);
       });
     case extent_types_t::TEST_BLOCK_PHYSICAL:
-      return get_extent<TestBlockPhysical>(offset, length
+      return get_extent<TestBlockPhysical>(
+          offset, length, p_metric_key
       ).safe_then([](auto extent) {
        return CachedExtentRef(extent.detach(), false /* add_ref */);
       });
index 19432f429020b5c9bfceb372832ca75c112fc28b..9c51cf446bb150edf6612acf62b96879eb54b3d8 100644 (file)
@@ -190,15 +190,17 @@ public:
    * - extent_set if already in cache
    * - disk
    */
+  using src_ext_t = std::pair<Transaction::src_t, extent_types_t>;
   using get_extent_ertr = base_ertr;
   template <typename T>
   using get_extent_ret = get_extent_ertr::future<TCachedExtentRef<T>>;
   template <typename T>
   get_extent_ret<T> get_extent(
-    paddr_t offset,       ///< [in] starting addr
-    segment_off_t length  ///< [in] length
+    paddr_t offset,                ///< [in] starting addr
+    segment_off_t length,          ///< [in] length
+    const src_ext_t* p_metric_key  ///< [in] cache query metric key
   ) {
-    auto cached = query_cache(offset);
+    auto cached = query_cache(offset, p_metric_key);
     if (!cached) {
       auto ret = CachedExtent::make_cached_extent_ref<T>(
         alloc_cache_buf(length));
@@ -246,7 +248,8 @@ public:
     get_extent_if_cached_iertr::future<CachedExtentRef>;
   get_extent_if_cached_ret get_extent_if_cached(
     Transaction &t,
-    paddr_t offset) {
+    paddr_t offset,
+    extent_types_t type) {
     CachedExtentRef ret;
     auto result = t.get_extent(offset, &ret);
     if (result != Transaction::get_extent_ret::ABSENT) {
@@ -256,7 +259,8 @@ public:
     }
 
     // get_extent_ret::ABSENT from transaction
-    ret = query_cache(offset);
+    auto metric_key = std::make_pair(t.get_src(), type);
+    ret = query_cache(offset, &metric_key);
     if (!ret ||
         // retired_placeholder is not really cached yet
         ret->get_type() == extent_types_t::RETIRED_PLACEHOLDER) {
@@ -295,8 +299,9 @@ public:
       return seastar::make_ready_future<TCachedExtentRef<T>>(
        ret->cast<T>());
     } else {
+      auto metric_key = std::make_pair(t.get_src(), T::TYPE);
       return trans_intr::make_interruptible(
-       get_extent<T>(offset, length)
+       get_extent<T>(offset, length, &metric_key)
       ).si_then(
        [&t, this](auto ref) {
          if (!ref->is_valid()) {
@@ -324,10 +329,11 @@ public:
    * and read in the extent at location offset~length.
    */
   get_extent_ertr::future<CachedExtentRef> get_extent_by_type(
-    extent_types_t type,  ///< [in] type tag
-    paddr_t offset,       ///< [in] starting addr
-    laddr_t laddr,        ///< [in] logical address if logical
-    segment_off_t length  ///< [in] length
+    extent_types_t type,             ///< [in] type tag
+    paddr_t offset,                  ///< [in] starting addr
+    laddr_t laddr,                   ///< [in] logical address if logical
+    segment_off_t length,            ///< [in] length
+    const Transaction::src_t* p_src  ///< [in] src tag for cache query metric
   );
 
   using get_extent_by_type_iertr = get_extent_iertr;
@@ -346,8 +352,9 @@ public:
     } else if (status == Transaction::get_extent_ret::PRESENT) {
       return seastar::make_ready_future<CachedExtentRef>(ret);
     } else {
+      auto src = t.get_src();
       return trans_intr::make_interruptible(
-       get_extent_by_type(type, offset, laddr, length)
+       get_extent_by_type(type, offset, laddr, length, &src)
       ).si_then([=, &t](CachedExtentRef ret) {
         if (!ret->is_valid()) {
           LOG_PREFIX(Cache::get_extent_by_type);
@@ -584,12 +591,18 @@ private:
    */
   CachedExtent::list dirty;
 
-  using src_ext_t = std::pair<Transaction::src_t, extent_types_t>;
+  struct query_counters_t {
+    uint64_t access;
+    uint64_t hit;
+  };
+
   struct {
     std::array<uint64_t, Transaction::SRC_MAX> trans_created_by_src;
     std::array<uint64_t, Transaction::SRC_MAX> trans_committed_by_src;
     std::unordered_map<src_ext_t, uint64_t,
                        boost::hash<src_ext_t>> trans_invalidated;
+    std::unordered_map<src_ext_t, query_counters_t,
+                       boost::hash<src_ext_t>> cache_query;
   } stats;
   uint64_t& get_counter(
       std::array<uint64_t, Transaction::SRC_MAX>& counters_by_src,
@@ -661,9 +674,22 @@ private:
   }
 
   // Extents in cache may contain placeholders
-  CachedExtentRef query_cache(paddr_t offset) {
+  CachedExtentRef query_cache(
+      paddr_t offset,
+      const src_ext_t* p_metric_key) {
+    query_counters_t* p_counters = nullptr;
+    if (p_metric_key) {
+      assert(stats.cache_query.count(*p_metric_key));
+      p_counters = &stats.cache_query[*p_metric_key];
+      ++p_counters->access;
+    }
     if (auto iter = extents.find_offset(offset);
         iter != extents.end()) {
+      if (p_metric_key &&
+          // retired_placeholder is not really cached yet
+          iter->get_type() != extent_types_t::RETIRED_PLACEHOLDER) {
+        ++p_counters->hit;
+      }
       return CachedExtentRef(&*iter);
     } else {
       return CachedExtentRef();
index f77fc76188579a0fae1f9cd1777572b451fec9db..f0e6b99243e8dc7415e1853ae02f7c0e64194672 100644 (file)
@@ -315,7 +315,7 @@ TransactionManager::get_extent_if_live_ret TransactionManager::get_extent_if_liv
   LOG_PREFIX(TransactionManager::get_extent_if_live);
   DEBUGT("type {}, addr {}, laddr {}, len {}", t, type, addr, laddr, len);
 
-  return cache->get_extent_if_cached(t, addr
+  return cache->get_extent_if_cached(t, addr, type
   ).si_then([this, FNAME, &t, type, addr, laddr, len](auto extent)
            -> get_extent_if_live_ret {
     if (extent) {