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;