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

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


The following commit(s) were added to refs/heads/master by this push:
     new 49bd4ec23 Hugepage support for iobuffer (#9228)
49bd4ec23 is described below

commit 49bd4ec23b55cfc8e9b40fe6550d21c2dae8bd36
Author: Chris McFarlen <ch...@mcfarlen.us>
AuthorDate: Thu Jan 5 15:04:36 2023 -0600

    Hugepage support for iobuffer (#9228)
    
    * Make iobufs use FreelistAllocator and updates to hugepages support
    
    * remove benchmark from Makefile
    
    * fix build issues
    
    * add missing documentation for new config items
    
    * fix table
    
    * provide default value for new config
    
    * remove todo that will not happen
    
    * use bool for use_hugepages variable
    
    Co-authored-by: Chris McFarlen <cmcfar...@apple.com>
---
 doc/admin-guide/files/records.config.en.rst | 46 +++++++++++++++++++++++++++
 include/tscore/Allocator.h                  | 24 ++++++++------
 include/tscore/ink_queue.h                  | 10 ++++--
 iocore/cache/Cache.cc                       |  6 +++-
 iocore/cache/CacheDir.cc                    |  4 +--
 iocore/cache/P_CacheInternal.h              |  1 +
 iocore/eventsystem/EventSystem.cc           | 24 +++++++++++++-
 iocore/eventsystem/IOBuffer.cc              | 24 +++++++++++---
 iocore/eventsystem/I_IOBuffer.h             |  3 +-
 mgmt/RecordsConfig.cc                       |  6 ++++
 proxy/http/remap/Makefile.am                |  1 +
 src/traffic_server/traffic_server.cc        |  8 ++---
 src/tscore/ink_queue.cc                     | 49 +++++++++++++++++++----------
 13 files changed, 162 insertions(+), 44 deletions(-)

diff --git a/doc/admin-guide/files/records.config.en.rst 
b/doc/admin-guide/files/records.config.en.rst
index b0ddaa630..068ae8c82 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -4916,6 +4916,52 @@ Sockets
    platforms.  (Currently only Linux).  IO buffers are allocated with the 
MADV_DONTDUMP
    with madvise() on Linux platforms that support MADV_DONTDUMP.  Enabled by 
default.
 
+.. ts:cv:: CONFIG proxy.config.allocator.iobuf_chunk_sizes STRING
+
+   This configures the chunk sizes of each of the IO buffer allocators.  The 
chunk size is the number
+   of buffers allocated in a batch when the allocator's freelist is exhausted. 
 This must be specified as a
+   space separated list of up to 15 numbers.  If not specified or if any value 
specified is 0, the default
+   value will be used.
+
+   The list of numbers will specify the chunk sizes in the following order:
+
+   ``128 256 512 1k 2k 4k 8k 16k 32k 64k 128k 256k 512k 1M 2M``
+
+   The defaults for each allocator is:
+
+   ``128 128 128 128 128 128 32 32 32 32 32 32 32 32 32``
+
+   Even though this is specified, the actual chunk size might be modified 
based on the system's page size (or hugepage
+   size if enabled).
+
+   You might want to adjust these values to reduce the overall number of 
allocations that ATS needs to make based
+   on your configured RAM cache size.  On a running system, you can send 
SIGUSR1 to the ATS process to have it
+   log the allocator statistics and see how many of each buffer size have been 
allocated.
+
+.. ts:cv:: CONFIG proxy.config.allocator.iobuf_use_hugepages INT 0
+
+   This setting controls whether huge pages allocations are used to allocate 
io buffers.  If enabled, and hugepages are
+   not available, this will fall back to normal size pages. Using hugepages 
for iobuffer can sometimes improve performance
+   by utilizing more of the TLB and reducing TLB misses.
+
+   ===== ======================================================================
+   Value Description
+   ===== ======================================================================
+   ``0`` IO buffer allocation uses normal pages sizes
+   ``1`` IO buffer allocation uses huge pages
+   ===== ======================================================================
+
+.. ts:cv:: CONFIG proxy.config.cache.dir.enable_hugepages INT 0
+
+   This setting controls whether huge pages allocations are used to allocate 
memory for cache volume dir entries.
+
+   ===== ======================================================================
+   Value Description
+   ===== ======================================================================
+   ``0`` Use normal pages sizes
+   ``1`` Use huge pages
+   ===== ======================================================================
+
 .. ts:cv:: CONFIG proxy.config.ssl.misc.io.max_buffer_index INT 8
 
    Configures the max IOBuffer Block index used for various SSL Operations
diff --git a/include/tscore/Allocator.h b/include/tscore/Allocator.h
index 2b630318a..00e1ce6a8 100644
--- a/include/tscore/Allocator.h
+++ b/include/tscore/Allocator.h
@@ -97,16 +97,18 @@ public:
     @param chunk_size number of units to be allocated if free pool is empty.
     @param alignment of objects must be a power of 2.
   */
-  FreelistAllocator(const char *name, unsigned int element_size, unsigned int 
chunk_size = 128, unsigned int alignment = 8)
+  FreelistAllocator(const char *name, unsigned int element_size, unsigned int 
chunk_size = 128, unsigned int alignment = 8,
+                    bool use_hugepages = false)
   {
-    ink_freelist_init(&fl, name, element_size, chunk_size, alignment);
+    ink_freelist_init(&fl, name, element_size, chunk_size, alignment, 
use_hugepages);
   }
 
   /** Re-initialize the parameters of the allocator. */
   void
-  re_init(const char *name, unsigned int element_size, unsigned int 
chunk_size, unsigned int alignment, int advice)
+  re_init(const char *name, unsigned int element_size, unsigned int 
chunk_size, unsigned int alignment, bool use_hugepages,
+          int advice)
   {
-    ink_freelist_madvise_init(&this->fl, name, element_size, chunk_size, 
alignment, advice);
+    ink_freelist_madvise_init(&this->fl, name, element_size, chunk_size, 
alignment, use_hugepages, advice);
   }
 
   // Dummies
@@ -186,14 +188,16 @@ public:
     @param chunk_size number of units to be allocated if free pool is empty.
     @param alignment of objects must be a power of 2.
   */
-  MallocAllocator(const char *name, unsigned int element_size, unsigned int 
chunk_size = 128, unsigned int alignment = 8)
+  MallocAllocator(const char *name, unsigned int element_size, unsigned int 
chunk_size = 128, unsigned int alignment = 8,
+                  bool use_hugepages = false)
     : element_size(element_size), alignment(alignment), advice(0)
   {
   }
 
   /** Re-initialize the parameters of the allocator. */
   void
-  re_init(const char *name, unsigned int element_size, unsigned int 
chunk_size, unsigned int alignment, int advice)
+  re_init(const char *name, unsigned int element_size, unsigned int 
chunk_size, unsigned int alignment, bool use_hugepages,
+          int advice)
   {
     this->element_size = element_size;
     this->alignment    = alignment;
@@ -227,7 +231,7 @@ using Allocator = FreelistAllocator;
   Allocator for Class objects.
 
 */
-template <class C, bool Destruct_on_free_ = false> class ClassAllocator : 
public Allocator
+template <class C, bool Destruct_on_free_ = false, typename BaseAllocator = 
Allocator> class ClassAllocator : public BaseAllocator
 {
 public:
   using Value_type                   = C;
@@ -238,7 +242,7 @@ public:
   C *
   alloc(Args &&... args)
   {
-    void *ptr = alloc_void();
+    void *ptr = this->alloc_void();
 
     ::new (ptr) C(std::forward<Args>(args)...);
     return reinterpret_cast<C *>(ptr);
@@ -254,7 +258,7 @@ public:
   {
     destroy_if_enabled(ptr);
 
-    free_void(ptr);
+    this->free_void(ptr);
   }
 
   /**
@@ -265,7 +269,7 @@ public:
     @param alignment of objects must be a power of 2.
   */
   ClassAllocator(const char *name, unsigned int chunk_size = 128, unsigned int 
alignment = 16)
-    : Allocator(name, static_cast<unsigned int>(RND16(sizeof(C))), chunk_size, 
static_cast<unsigned int>(RND16(alignment)))
+    : BaseAllocator(name, static_cast<unsigned int>(RND16(sizeof(C))), 
chunk_size, static_cast<unsigned int>(RND16(alignment)))
   {
   }
 
diff --git a/include/tscore/ink_queue.h b/include/tscore/ink_queue.h
index 4b8f02873..517fdab1e 100644
--- a/include/tscore/ink_queue.h
+++ b/include/tscore/ink_queue.h
@@ -191,6 +191,8 @@ struct _InkFreeList {
   const char *name;
   uint32_t type_size, chunk_size, used, allocated, alignment;
   uint32_t allocated_base, used_base;
+  uint32_t hugepages_failure;
+  bool use_hugepages;
   int advice;
 };
 
@@ -204,11 +206,13 @@ void ink_freelist_init_ops(int nofl_class, int 
nofl_proxy);
 /*
  * alignment must be a power of 2
  */
-InkFreeList *ink_freelist_create(const char *name, uint32_t type_size, 
uint32_t chunk_size, uint32_t alignment);
+InkFreeList *ink_freelist_create(const char *name, uint32_t type_size, 
uint32_t chunk_size, uint32_t alignment,
+                                 bool use_hugepages = false);
 
-void ink_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size, 
uint32_t chunk_size, uint32_t alignment);
+void ink_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size, 
uint32_t chunk_size, uint32_t alignment,
+                       bool use_hugepages);
 void ink_freelist_madvise_init(InkFreeList **fl, const char *name, uint32_t 
type_size, uint32_t chunk_size, uint32_t alignment,
-                               int advice);
+                               bool use_hugepages, int advice);
 void *ink_freelist_new(InkFreeList *f);
 void ink_freelist_free(InkFreeList *f, void *item);
 void ink_freelist_free_bulk(InkFreeList *f, void *head, void *tail, size_t 
num_item);
diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc
index dd1751b41..87aca4073 100644
--- a/iocore/cache/Cache.cc
+++ b/iocore/cache/Cache.cc
@@ -83,6 +83,7 @@ int cache_config_read_while_writer             = 0;
 int cache_config_mutex_retry_delay             = 2;
 int cache_read_while_writer_retry_delay        = 50;
 int cache_config_read_while_writer_max_retries = 10;
+int cache_config_dir_enable_hugepages          = 0;
 
 // Globals
 
@@ -1253,7 +1254,7 @@ Vol::init(char *s, off_t blocks, off_t dir_skip, bool 
clear)
         (long long)this->len, (double)dirlen() / (double)this->len * 100.0);
 
   raw_dir = nullptr;
-  if (ats_hugepage_enabled()) {
+  if (ats_hugepage_enabled() && cache_config_dir_enable_hugepages) {
     raw_dir = static_cast<char *>(ats_alloc_hugepage(this->dirlen()));
   }
   if (raw_dir == nullptr) {
@@ -3153,6 +3154,9 @@ ink_cache_init(ts::ModuleVersion v)
   REC_EstablishStaticConfigInt32(cache_config_dir_sync_frequency, 
"proxy.config.cache.dir.sync_frequency");
   Debug("cache_init", "proxy.config.cache.dir.sync_frequency = %d", 
cache_config_dir_sync_frequency);
 
+  REC_EstablishStaticConfigInt32(cache_config_dir_enable_hugepages, 
"proxy.config.cache.dir.enable_hugepages");
+  Debug("cache_init", "proxy.config.cache.dir.enable_hugepages = %d", 
cache_config_dir_enable_hugepages);
+
   REC_EstablishStaticConfigInt32(cache_config_select_alternate, 
"proxy.config.cache.select_alternate");
   Debug("cache_init", "proxy.config.cache.select_alternate = %d", 
cache_config_select_alternate);
 
diff --git a/iocore/cache/CacheDir.cc b/iocore/cache/CacheDir.cc
index 2eac710b8..b73eea0d3 100644
--- a/iocore/cache/CacheDir.cc
+++ b/iocore/cache/CacheDir.cc
@@ -994,7 +994,7 @@ sync_cache_dir_on_shutdown()
         buf = nullptr;
       }
       buflen = dirlen;
-      if (ats_hugepage_enabled()) {
+      if (ats_hugepage_enabled() && cache_config_dir_enable_hugepages) {
         buf      = static_cast<char *>(ats_alloc_hugepage(buflen));
         buf_huge = true;
       }
@@ -1126,7 +1126,7 @@ Lrestart:
           buf = nullptr;
         }
         buflen = dirlen;
-        if (ats_hugepage_enabled()) {
+        if (ats_hugepage_enabled() && cache_config_dir_enable_hugepages) {
           buf      = static_cast<char *>(ats_alloc_hugepage(buflen));
           buf_huge = true;
         }
diff --git a/iocore/cache/P_CacheInternal.h b/iocore/cache/P_CacheInternal.h
index a8bba8d4a..22c87830f 100644
--- a/iocore/cache/P_CacheInternal.h
+++ b/iocore/cache/P_CacheInternal.h
@@ -209,6 +209,7 @@ extern RecRawStatBlock *cache_rsb;
 
 // Configuration
 extern int cache_config_dir_sync_frequency;
+extern int cache_config_dir_enable_hugepages;
 extern int cache_config_http_max_alts;
 extern int cache_config_log_alternate_eviction;
 extern int cache_config_permit_pinning;
diff --git a/iocore/eventsystem/EventSystem.cc 
b/iocore/eventsystem/EventSystem.cc
index 14971779d..49ff87091 100644
--- a/iocore/eventsystem/EventSystem.cc
+++ b/iocore/eventsystem/EventSystem.cc
@@ -29,6 +29,7 @@
 ****************************************************************************/
 
 #include "P_EventSystem.h"
+#include "tscore/hugepages.h"
 
 void
 ink_event_system_init(ts::ModuleVersion v)
@@ -42,6 +43,27 @@ ink_event_system_init(ts::ModuleVersion v)
 
   REC_EstablishStaticConfigInt32(thread_freelist_low_watermark, 
"proxy.config.allocator.thread_freelist_low_watermark");
 
+  int chunk_sizes[DEFAULT_BUFFER_SIZES] = {0};
+  char *chunk_sizes_string              = 
REC_ConfigReadString("proxy.config.allocator.iobuf_chunk_sizes");
+  if (chunk_sizes_string != nullptr) {
+    ts::TextView src(chunk_sizes_string, ts::TextView::npos);
+    int n = 0;
+    while (n < DEFAULT_BUFFER_SIZES && !src.empty()) {
+      ts::TextView token{src.take_prefix_at(' ')};
+      auto x = ts::svto_radix<10>(token);
+      if (token.empty() && x <= std::numeric_limits<int>::max()) {
+        chunk_sizes[n++] = x;
+      } else {
+        break;
+      }
+    }
+    ats_free(chunk_sizes_string);
+  }
+
+  int hugepage_config = 
REC_ConfigReadInteger("proxy.config.allocator.iobuf_use_hugepages");
+
+  bool use_hugepages = ats_hugepage_enabled() && hugepage_config == 1;
+
 #ifdef MADV_DONTDUMP // This should only exist on Linux 3.4 and higher.
   RecBool dont_dump_enabled = true;
   RecGetRecordBool("proxy.config.allocator.dontdump_iobuffers", 
&dont_dump_enabled, false);
@@ -51,5 +73,5 @@ ink_event_system_init(ts::ModuleVersion v)
   }
 #endif
 
-  init_buffer_allocators(iobuffer_advice);
+  init_buffer_allocators(iobuffer_advice, chunk_sizes, use_hugepages);
 }
diff --git a/iocore/eventsystem/IOBuffer.cc b/iocore/eventsystem/IOBuffer.cc
index b47bac383..805886dfa 100644
--- a/iocore/eventsystem/IOBuffer.cc
+++ b/iocore/eventsystem/IOBuffer.cc
@@ -31,7 +31,7 @@
 //
 // General Buffer Allocator
 //
-Allocator ioBufAllocator[DEFAULT_BUFFER_SIZES];
+FreelistAllocator ioBufAllocator[DEFAULT_BUFFER_SIZES];
 ClassAllocator<MIOBuffer> ioAllocator("ioAllocator", DEFAULT_BUFFER_NUMBER);
 ClassAllocator<IOBufferData> ioDataAllocator("ioDataAllocator", 
DEFAULT_BUFFER_NUMBER);
 ClassAllocator<IOBufferBlock> ioBlockAllocator("ioBlockAllocator", 
DEFAULT_BUFFER_NUMBER);
@@ -43,22 +43,36 @@ int64_t max_iobuffer_size           = DEFAULT_BUFFER_SIZES 
- 1;
 // Initialization
 //
 void
-init_buffer_allocators(int iobuffer_advice)
+init_buffer_allocators(int iobuffer_advice, int 
chunk_sizes[DEFAULT_BUFFER_SIZES], bool use_hugepages)
 {
   for (int i = 0; i < DEFAULT_BUFFER_SIZES; i++) {
     int64_t s = DEFAULT_BUFFER_BASE_SIZE * ((static_cast<int64_t>(1)) << i);
     int64_t a = DEFAULT_BUFFER_ALIGNMENT;
-    int n     = i <= default_large_iobuffer_size ? DEFAULT_BUFFER_NUMBER : 
DEFAULT_HUGE_BUFFER_NUMBER;
+    int n     = chunk_sizes[i];
+    if (n == 0) {
+      n = i <= default_large_iobuffer_size ? DEFAULT_BUFFER_NUMBER : 
DEFAULT_HUGE_BUFFER_NUMBER;
+    }
     if (s < a) {
       a = s;
     }
 
     auto name = new char[64];
-    snprintf(name, 64, "ioBufAllocator[%d]", i);
-    ioBufAllocator[i].re_init(name, s, n, a, iobuffer_advice);
+    if (use_hugepages) {
+      snprintf(name, 64, "ioBufAllocatorHP[%d]", i);
+    } else {
+      snprintf(name, 64, "ioBufAllocator[%d]", i);
+    }
+    ioBufAllocator[i].re_init(name, s, n, a, use_hugepages, iobuffer_advice);
   }
 }
 
+void
+init_buffer_allocators(int iobuffer_advice)
+{
+  int chunk_sizes[DEFAULT_BUFFER_SIZES] = {0};
+  init_buffer_allocators(iobuffer_advice, chunk_sizes, false);
+}
+
 //
 // MIOBuffer
 //
diff --git a/iocore/eventsystem/I_IOBuffer.h b/iocore/eventsystem/I_IOBuffer.h
index 8d8c0acc6..b179d8051 100644
--- a/iocore/eventsystem/I_IOBuffer.h
+++ b/iocore/eventsystem/I_IOBuffer.h
@@ -110,8 +110,9 @@ enum AllocType {
 #define BUFFER_SIZE_FOR_CONSTANT(_size) (_size - DEFAULT_BUFFER_SIZES)
 #define BUFFER_SIZE_INDEX_FOR_CONSTANT_SIZE(_size) (_size + 
DEFAULT_BUFFER_SIZES)
 
-extern Allocator ioBufAllocator[DEFAULT_BUFFER_SIZES];
+extern FreelistAllocator ioBufAllocator[DEFAULT_BUFFER_SIZES];
 
+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/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index c69481385..9aa9af3ee 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -856,6 +856,8 @@ static const RecordElement RecordsConfig[] =
   //  # how often should the directory be synced (seconds)
   {RECT_CONFIG, "proxy.config.cache.dir.sync_frequency", RECD_INT, "60", 
RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
   ,
+  {RECT_CONFIG, "proxy.config.cache.dir.enable_hugepages", RECD_INT, "0", 
RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
   {RECT_CONFIG, "proxy.config.cache.hostdb.disable_reverse_lookup", RECD_INT, 
"0", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
   ,
   {RECT_CONFIG, "proxy.config.cache.select_alternate", RECD_INT, "1", 
RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
@@ -1548,6 +1550,10 @@ static const RecordElement RecordsConfig[] =
   ,
   {RECT_CONFIG, "proxy.config.allocator.dontdump_iobuffers", RECD_INT, "1", 
RECU_RESTART_TS, RR_NULL, RECC_NULL, "[0-1]", RECA_NULL}
   ,
+  {RECT_CONFIG, "proxy.config.allocator.iobuf_chunk_sizes", RECD_STRING, 
nullptr, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
+  {RECT_CONFIG, "proxy.config.allocator.iobuf_use_hugepages", RECD_INT, "0", 
RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
 
   // Controls for TLS ASYN_JOBS and engine loading
   {RECT_CONFIG, "proxy.config.ssl.async.handshake.enabled", RECD_INT, "0", 
RECU_RESTART_TS, RR_NULL, RECC_NULL, "[0-1]", RECA_NULL},
diff --git a/proxy/http/remap/Makefile.am b/proxy/http/remap/Makefile.am
index daba213c0..9d2343112 100644
--- a/proxy/http/remap/Makefile.am
+++ b/proxy/http/remap/Makefile.am
@@ -72,6 +72,7 @@ COMMON_PLUGINDSO_LDADDS = \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/tscore/libtscore.la \
+       $(top_builddir)/src/tscpp/util/libtscpputil.la \
        $(top_builddir)/mgmt/libmgmt_p.la \
        $(top_builddir)/proxy/shared/libUglyLogStubs.a \
        @HWLOC_LIBS@
diff --git a/src/traffic_server/traffic_server.cc 
b/src/traffic_server/traffic_server.cc
index c5c44fa07..7c067e128 100644
--- a/src/traffic_server/traffic_server.cc
+++ b/src/traffic_server/traffic_server.cc
@@ -271,15 +271,15 @@ public:
     if (signal_received[SIGUSR1]) {
       signal_received[SIGUSR1] = false;
 
-      // TODO: TS-567 Integrate with debugging allocators "dump" features?
-      ink_freelists_dump(stderr);
-      ResourceTracker::dump(stderr);
-
 #if TS_HAS_JEMALLOC
       char buf[PATH_NAME_MAX] = "";
       RecGetRecordString("proxy.config.memory.malloc_stats_print_opts", buf, 
PATH_NAME_MAX);
       malloc_stats_print(nullptr, nullptr, buf);
 #endif
+
+      // TODO: TS-567 Integrate with debugging allocators "dump" features?
+      ink_freelists_dump(stderr);
+      ResourceTracker::dump(stderr);
     }
 
     if (signal_received[SIGUSR2]) {
diff --git a/src/tscore/ink_queue.cc b/src/tscore/ink_queue.cc
index 6446113e4..c4364c122 100644
--- a/src/tscore/ink_queue.cc
+++ b/src/tscore/ink_queue.cc
@@ -117,7 +117,8 @@ ink_freelist_init_ops(int nofl_class, int nofl_proxy)
 }
 
 void
-ink_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size, 
uint32_t chunk_size, uint32_t alignment)
+ink_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size, 
uint32_t chunk_size, uint32_t alignment,
+                  bool use_hugepages)
 {
   InkFreeList *f;
   ink_freelist_list *fll;
@@ -137,15 +138,23 @@ ink_freelist_init(InkFreeList **fl, const char *name, 
uint32_t type_size, uint32
   ink_assert(!(alignment & (alignment - 1)));
   // It is never useful to have alignment requirement looser than a page size
   // so clip it. This makes the item alignment checks in the actual allocator 
simpler.
-  f->alignment = alignment;
-  if (f->alignment > ats_pagesize()) {
-    f->alignment = ats_pagesize();
+  f->alignment         = alignment;
+  f->use_hugepages     = ats_hugepage_enabled() && use_hugepages;
+  f->hugepages_failure = 0;
+  if (f->use_hugepages) {
+    // for hugepages, always make the allocation alignment on a hugepage 
boundary
+    f->alignment = ats_hugepage_size();
+    f->type_size = type_size;
+  } else {
+    if (f->alignment > ats_pagesize()) {
+      f->alignment = ats_pagesize();
+    }
+    // Make sure we align *all* the objects in the allocation, not just the 
first one
+    f->type_size = INK_ALIGN(type_size, f->alignment);
   }
   Debug(DEBUG_TAG "_init", "<%s> Alignment request/actual (%" PRIu32 "/%" 
PRIu32 ")", name, alignment, f->alignment);
-  // Make sure we align *all* the objects in the allocation, not just the 
first one
-  f->type_size = INK_ALIGN(type_size, f->alignment);
   Debug(DEBUG_TAG "_init", "<%s> Type Size request/actual (%" PRIu32 "/%" 
PRIu32 ")", name, type_size, f->type_size);
-  if (ats_hugepage_enabled()) {
+  if (f->use_hugepages) {
     f->chunk_size = INK_ALIGN(chunk_size * f->type_size, ats_hugepage_size()) 
/ f->type_size;
   } else {
     f->chunk_size = INK_ALIGN(chunk_size * f->type_size, ats_pagesize()) / 
f->type_size;
@@ -158,18 +167,18 @@ ink_freelist_init(InkFreeList **fl, const char *name, 
uint32_t type_size, uint32
 
 void
 ink_freelist_madvise_init(InkFreeList **fl, const char *name, uint32_t 
type_size, uint32_t chunk_size, uint32_t alignment,
-                          int advice)
+                          bool use_hugepages, int advice)
 {
-  ink_freelist_init(fl, name, type_size, chunk_size, alignment);
+  ink_freelist_init(fl, name, type_size, chunk_size, alignment, use_hugepages);
   (*fl)->advice = advice;
 }
 
 InkFreeList *
-ink_freelist_create(const char *name, uint32_t type_size, uint32_t chunk_size, 
uint32_t alignment)
+ink_freelist_create(const char *name, uint32_t type_size, uint32_t chunk_size, 
uint32_t alignment, bool use_hugepages)
 {
   InkFreeList *f;
 
-  ink_freelist_init(&f, name, type_size, chunk_size, alignment);
+  ink_freelist_init(&f, name, type_size, chunk_size, alignment, use_hugepages);
   return f;
 }
 
@@ -206,9 +215,12 @@ freelist_new(InkFreeList *f)
       size_t alloc_size = f->chunk_size * f->type_size;
       size_t alignment  = 0;
 
-      if (ats_hugepage_enabled()) {
+      if (f->use_hugepages) {
         alignment = ats_hugepage_size();
         newp      = ats_alloc_hugepage(alloc_size);
+        if (newp == nullptr) {
+          f->hugepages_failure++;
+        }
       }
 
       if (newp == nullptr) {
@@ -451,17 +463,20 @@ ink_freelists_dump(FILE *f)
     f = stderr;
   }
 
-  fprintf(f, "     Allocated      |        In-Use      | Type Size  |   Free 
List Name\n");
-  fprintf(f, 
"--------------------|--------------------|------------|----------------------------------\n");
+  fprintf(f, "     Allocated      |   Allocated Count  |        In-Use      |  
  In-Use Count    | Type Size  | Chunk Size | HP "
+             "Fails |   Free List Name\n");
+  fprintf(f, 
"--------------------|--------------------|--------------------|--------------------|------------|------------|-------"
+             "---|----------------------------------\n");
 
   uint64_t total_allocated = 0;
   uint64_t total_used      = 0;
   fll                      = freelists;
   while (fll) {
-    fprintf(f, " %18" PRIu64 " | %18" PRIu64 " | %10u | memory/%s\n",
+    fprintf(f, " %18" PRIu64 " | %18" PRIu64 " | %18" PRIu64 " | %18" PRIu64 " 
| %10u | %10u | %10u | memory/%s\n",
             static_cast<uint64_t>(fll->fl->allocated) * 
static_cast<uint64_t>(fll->fl->type_size),
-            static_cast<uint64_t>(fll->fl->used) * 
static_cast<uint64_t>(fll->fl->type_size), fll->fl->type_size,
-            fll->fl->name ? fll->fl->name : "<unknown>");
+            static_cast<uint64_t>(fll->fl->allocated),
+            static_cast<uint64_t>(fll->fl->used) * 
static_cast<uint64_t>(fll->fl->type_size), static_cast<uint64_t>(fll->fl->used),
+            fll->fl->type_size, fll->fl->chunk_size, 
fll->fl->hugepages_failure, fll->fl->name ? fll->fl->name : "<unknown>");
     total_allocated += static_cast<uint64_t>(fll->fl->allocated) * 
static_cast<uint64_t>(fll->fl->type_size);
     total_used += static_cast<uint64_t>(fll->fl->used) * 
static_cast<uint64_t>(fll->fl->type_size);
     fll = fll->next;

Reply via email to