This is an automated email from the ASF dual-hosted git repository.

cmcfarlen pushed a commit to branch 10.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit 8e3cc5c9c1ecd76c5d23ab01ce969dd8dd38578d
Author: Chris McFarlen <[email protected]>
AuthorDate: Mon Jun 10 10:09:16 2024 -0500

    Add metrics to memory Allocators (#11413)
    
    * Add metrics to memory Allocators
    
    * Add build option to enable allocator metrics
    
    ---------
    
    Co-authored-by: Chris McFarlen <[email protected]>
    (cherry picked from commit 17ab9a9764671927c6346f1764eedcdf6d9f6bce)
---
 CMakeLists.txt                        |  2 +
 include/iocore/eventsystem/IOBuffer.h |  4 ++
 include/tscore/Allocator.h            | 90 +++++++++++++++++++++++++++++++++--
 include/tscore/ink_config.h.cmake.in  |  1 +
 include/tsutil/Metrics.h              | 18 +++++++
 src/iocore/eventsystem/IOBuffer.cc    |  7 ++-
 6 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0916dab4bf..5433cf6978 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -122,6 +122,7 @@ set(DEFAULT_STACK_SIZE
 )
 option(ENABLE_FAST_SDK "Use fast SDK APIs (default OFF)")
 option(ENABLE_MALLOC_ALLOCATOR "Use direct malloc allocator over freelist 
allocator (default OFF)")
+option(ENABLE_ALLOCATOR_METRICS "Enable metrics for Allocators (default OFF)")
 option(ENABLE_DOCS "Build docs (default OFF)")
 option(ENABLE_DISK_FAILURE_TESTS "Build disk failure tests (enables AIO fault 
injection, default OFF)" OFF)
 if(ENABLE_DISK_FAILURE_TESTS)
@@ -329,6 +330,7 @@ if(ENABLE_PROBES)
 endif()
 
 set(TS_USE_MALLOC_ALLOCATOR ${ENABLE_MALLOC_ALLOCATOR})
+set(TS_USE_ALLOCATOR_METRICS ${ENABLE_ALLOCATOR_METRICS})
 find_package(ZLIB REQUIRED)
 
 # ncurses is used in traffic_top
diff --git a/include/iocore/eventsystem/IOBuffer.h 
b/include/iocore/eventsystem/IOBuffer.h
index 3487b2a880..c0d38d325d 100644
--- a/include/iocore/eventsystem/IOBuffer.h
+++ b/include/iocore/eventsystem/IOBuffer.h
@@ -110,7 +110,11 @@ enum AllocType {
 #define BUFFER_SIZE_FOR_CONSTANT(_size)            (_size - 
DEFAULT_BUFFER_SIZES)
 #define BUFFER_SIZE_INDEX_FOR_CONSTANT_SIZE(_size) (_size + 
DEFAULT_BUFFER_SIZES)
 
+#if TS_USE_ALLOCATOR_METRICS
+extern MeteredAllocator<FreelistAllocator> 
ioBufAllocator[DEFAULT_BUFFER_SIZES];
+#else
 extern FreelistAllocator ioBufAllocator[DEFAULT_BUFFER_SIZES];
+#endif
 
 void init_buffer_allocators(int iobuffer_advice, int 
chunk_sizes[DEFAULT_BUFFER_SIZES], bool use_hugepages);
 void init_buffer_allocators(int iobuffer_advice);
diff --git a/include/tscore/Allocator.h b/include/tscore/Allocator.h
index d1a6cbdb2b..785dbae28a 100644
--- a/include/tscore/Allocator.h
+++ b/include/tscore/Allocator.h
@@ -39,12 +39,11 @@
 
 #pragma once
 
-#include <new>
 #include <cstdlib>
 #include <utility>
 #include "tscore/ink_queue.h"
-#include "tscore/ink_defs.h"
 #include "tscore/ink_resource.h"
+#include "tsutil/Metrics.h"
 #include <execinfo.h>
 
 #define RND16(_x) (((_x) + 15) & ~15)
@@ -156,7 +155,7 @@ public:
   void
   free_void(void *ptr)
   {
-    free(ptr);
+    ::free(ptr);
   }
 
   /**
@@ -221,11 +220,94 @@ private:
   int          advice;
 };
 
+#if TS_USE_ALLOCATOR_METRICS
+template <typename WrappedAllocator> class MeteredAllocator : public 
WrappedAllocator
+{
+public:
+  void *
+  alloc_void()
+  {
+    inuse_metric->increment(1);
+    alloc_metric->increment(1);
+    return WrappedAllocator::alloc_void();
+  }
+
+  void
+  free_void(void *ptr)
+  {
+    inuse_metric->decrement(1);
+    free_metric->increment(1);
+    WrappedAllocator::free_void(ptr);
+  }
+
+  void
+  free_void_bulk(void *head, void *tail, size_t num_item)
+  {
+    inuse_metric->decrement(num_item);
+    free_metric->increment(num_item);
+    WrappedAllocator::free_void_bulk(head, tail, num_item);
+  }
+
+  MeteredAllocator() {}
+
+  MeteredAllocator(const char *name, unsigned int element_size, unsigned int 
chunk_size = 128, unsigned int alignment = 8,
+                   bool use_hugepages = false)
+    : WrappedAllocator(name, element_size, chunk_size, alignment, 
use_hugepages),
+      
inuse_metric{ts::Metrics::Gauge::createPtr("proxy.process.allocator.inuse.", 
name)},
+      
alloc_metric{ts::Metrics::Counter::createPtr("proxy.process.allocator.alloc.", 
name)},
+      
free_metric{ts::Metrics::Counter::createPtr("proxy.process.allocator.free.", 
name)},
+      
size_metric{ts::Metrics::Gauge::createPtr("proxy.process.allocator.size.", 
name)}
+  {
+    size_metric->store(element_size);
+  }
+
+  void
+  re_init(const char *name, unsigned int element_size, unsigned int 
chunk_size, unsigned int alignment, bool use_hugepages,
+          int advice)
+  {
+    if (inuse_metric == nullptr) {
+      inuse_metric = 
ts::Metrics::Gauge::createPtr("proxy.process.allocator.inuse.", name);
+      alloc_metric = 
ts::Metrics::Counter::createPtr("proxy.process.allocator.alloc.", name);
+      free_metric  = 
ts::Metrics::Counter::createPtr("proxy.process.allocator.free.", name);
+      size_metric  = 
ts::Metrics::Gauge::createPtr("proxy.process.allocator.size.", name);
+    }
+    size_metric->store(element_size);
+
+    WrappedAllocator::re_init(name, element_size, chunk_size, alignment, 
use_hugepages, advice);
+  }
+
+  void
+  destroy_if_enabled(void *p)
+  {
+    WrappedAllocator::destroy_if_enabled(p);
+  }
+
+  // for metered allocator we don't want to return superclass or we'll skip 
metrics (see THREAD_FREE macro)
+  MeteredAllocator<WrappedAllocator> &
+  raw()
+  {
+    return *this;
+  }
+
+private:
+  ts::Metrics::AtomicType *inuse_metric = nullptr;
+  ts::Metrics::AtomicType *alloc_metric = nullptr;
+  ts::Metrics::AtomicType *free_metric  = nullptr;
+  ts::Metrics::AtomicType *size_metric  = nullptr;
+};
+
+#if TS_USE_MALLOC_ALLOCATOR
+using Allocator = MeteredAllocator<MallocAllocator>;
+#else
+using Allocator = MeteredAllocator<FreelistAllocator>;
+#endif
+#else
 #if TS_USE_MALLOC_ALLOCATOR
 using Allocator = MallocAllocator;
 #else
 using Allocator = FreelistAllocator;
 #endif
+#endif // TS_USE_ALLOCATOR_METRICS
 
 /**
   Allocator for Class objects.
@@ -273,7 +355,7 @@ public:
   {
   }
 
-  Allocator &
+  BaseAllocator &
   raw()
   {
     return *this;
diff --git a/include/tscore/ink_config.h.cmake.in 
b/include/tscore/ink_config.h.cmake.in
index 554d19d630..c9ac033886 100644
--- a/include/tscore/ink_config.h.cmake.in
+++ b/include/tscore/ink_config.h.cmake.in
@@ -149,6 +149,7 @@ const int DEFAULT_STACKSIZE = @DEFAULT_STACK_SIZE@;
 #cmakedefine01 TS_USE_KQUEUE
 #cmakedefine01 TS_USE_LINUX_IO_URING
 #cmakedefine01 TS_USE_MALLOC_ALLOCATOR
+#cmakedefine01 TS_USE_ALLOCATOR_METRICS
 #cmakedefine01 TS_USE_POSIX_CAP
 #cmakedefine01 TS_USE_QUIC
 #cmakedefine01 TS_USE_REMOTE_UNWINDING
diff --git a/include/tsutil/Metrics.h b/include/tsutil/Metrics.h
index 80da30fd71..cc309a5b60 100644
--- a/include/tsutil/Metrics.h
+++ b/include/tsutil/Metrics.h
@@ -395,6 +395,15 @@ public:
       return reinterpret_cast<AtomicType 
*>(instance.lookup(instance._create(name)));
     }
 
+    static AtomicType *
+    createPtr(const std::string_view prefix, const std::string_view name)
+    {
+      auto       &instance = Metrics::instance();
+      std::string tmpname  = std::string(prefix) + std::string(name);
+
+      return reinterpret_cast<AtomicType 
*>(instance.lookup(instance._create(tmpname)));
+    }
+
     static Metrics::Gauge::SpanType
     createSpan(size_t size, IdType *id = nullptr)
     {
@@ -483,6 +492,15 @@ public:
       return reinterpret_cast<AtomicType 
*>(instance.lookup(instance._create(name)));
     }
 
+    static AtomicType *
+    createPtr(const std::string_view prefix, const std::string_view name)
+    {
+      auto       &instance = Metrics::instance();
+      std::string tmpname  = std::string(prefix) + std::string(name);
+
+      return reinterpret_cast<AtomicType 
*>(instance.lookup(instance._create(tmpname)));
+    }
+
     static Metrics::Counter::SpanType
     createSpan(size_t size, IdType *id = nullptr)
     {
diff --git a/src/iocore/eventsystem/IOBuffer.cc 
b/src/iocore/eventsystem/IOBuffer.cc
index fb82b40776..66decc4bac 100644
--- a/src/iocore/eventsystem/IOBuffer.cc
+++ b/src/iocore/eventsystem/IOBuffer.cc
@@ -25,6 +25,7 @@
   UIOBuffer.cc
 
 **************************************************************************/
+#include "tscore/Allocator.h"
 #include "tscore/ink_defs.h"
 #include "P_EventSystem.h"
 #include "swoc/Lexicon.h"
@@ -34,7 +35,11 @@
 //
 // General Buffer Allocator
 //
-FreelistAllocator             ioBufAllocator[DEFAULT_BUFFER_SIZES];
+#if TS_USE_ALLOCATOR_METRICS
+MeteredAllocator<FreelistAllocator> ioBufAllocator[DEFAULT_BUFFER_SIZES];
+#else
+FreelistAllocator ioBufAllocator[DEFAULT_BUFFER_SIZES];
+#endif
 ClassAllocator<MIOBuffer>     ioAllocator("ioAllocator", 
DEFAULT_BUFFER_NUMBER);
 ClassAllocator<IOBufferData>  ioDataAllocator("ioDataAllocator", 
DEFAULT_BUFFER_NUMBER);
 ClassAllocator<IOBufferBlock> ioBlockAllocator("ioBlockAllocator", 
DEFAULT_BUFFER_NUMBER);

Reply via email to