diff --git a/doc/admin-guide/files/records.yaml.en.rst b/doc/admin-guide/files/records.yaml.en.rst index 9be55369f8f..6a8732afb85 100644 --- a/doc/admin-guide/files/records.yaml.en.rst +++ b/doc/admin-guide/files/records.yaml.en.rst @@ -4966,13 +4966,18 @@ Sockets Enable (1) the use of huge pages on supported platforms. (Currently only Linux) You must also enable hugepages at the OS level. In modern Linux kernels, - this can be done by setting ``/proc/sys/vm/nr_overcommit_hugepages`` to a - sufficiently large value. It is reasonable to use (system - memory/hugepage size) because these pages are only created on demand. + this can be done by setting ``/proc/sys/vm/nr_hugepages`` and/or ``/proc/sys/vm/nr_overcommit_hugepages`` + to a sufficiently large value. Check your system hugepage size (typically 2MB) using + ``/proc/meminfo`` (look for ``Hugepagesize``). The configured number of ``nr_hugepages`` plus + ``nr_overcommit_hugepages`` times the hugepage size will be the amount of ram availabe for hugepages. For more information on the implications of enabling huge pages, see `Wikipedia _`. + If hugepages are enabled, then the iobuffer allocator and cache directory entries will attempt to allocate + hugepages for storage. If the number of hugepages is exhausted, the allocators will revert back to regular + size pages. + .. ts:cv:: CONFIG proxy.config.dump_mem_info_frequency INT 0 :reloadable: @@ -5022,30 +5027,6 @@ Sockets 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/iocore/cache/Cache.cc b/iocore/cache/Cache.cc index 80acb209d3e..db0c7e5a60d 100644 --- a/iocore/cache/Cache.cc +++ b/iocore/cache/Cache.cc @@ -83,7 +83,6 @@ 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 @@ -1255,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() && cache_config_dir_enable_hugepages) { + if (ats_hugepage_enabled()) { raw_dir = static_cast(ats_alloc_hugepage(this->dirlen())); } if (raw_dir == nullptr) { @@ -3159,9 +3158,6 @@ 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 6baf3be8425..e09c39286f5 100644 --- a/iocore/cache/CacheDir.cc +++ b/iocore/cache/CacheDir.cc @@ -1017,7 +1017,7 @@ sync_cache_dir_on_shutdown() buf = nullptr; } buflen = dirlen; - if (ats_hugepage_enabled() && cache_config_dir_enable_hugepages) { + if (ats_hugepage_enabled()) { buf = static_cast(ats_alloc_hugepage(buflen)); buf_huge = true; } @@ -1149,7 +1149,7 @@ CacheSync::mainEvent(int event, Event *e) buf = nullptr; } buflen = dirlen; - if (ats_hugepage_enabled() && cache_config_dir_enable_hugepages) { + if (ats_hugepage_enabled()) { buf = static_cast(ats_alloc_hugepage(buflen)); buf_huge = true; } diff --git a/iocore/cache/P_CacheInternal.h b/iocore/cache/P_CacheInternal.h index b3bdda40bbb..d769029cd3a 100644 --- a/iocore/cache/P_CacheInternal.h +++ b/iocore/cache/P_CacheInternal.h @@ -210,7 +210,6 @@ 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 cf3c989197e..b26fc7acf9a 100644 --- a/iocore/eventsystem/EventSystem.cc +++ b/iocore/eventsystem/EventSystem.cc @@ -45,24 +45,12 @@ ink_event_system_init(ts::ModuleVersion v) 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::max()) { - chunk_sizes[n++] = x; - } else { - break; - } - } - ats_free(chunk_sizes_string); + if (chunk_sizes_string && !parse_buffer_chunk_sizes(chunk_sizes_string, chunk_sizes)) { + // If we can't parse the string then we can't be sure of the chunk sizes so just exit + Fatal("Failed to parse proxy.config.allocator.iobuf_chunk_sizes"); } - int hugepage_config = REC_ConfigReadInteger("proxy.config.allocator.iobuf_use_hugepages"); - - bool use_hugepages = ats_hugepage_enabled() && hugepage_config == 1; + bool use_hugepages = ats_hugepage_enabled(); #ifdef MADV_DONTDUMP // This should only exist on Linux 3.4 and higher. RecBool dont_dump_enabled = true; diff --git a/iocore/eventsystem/IOBuffer.cc b/iocore/eventsystem/IOBuffer.cc index 55e0c174910..26f85896cc1 100644 --- a/iocore/eventsystem/IOBuffer.cc +++ b/iocore/eventsystem/IOBuffer.cc @@ -27,6 +27,9 @@ **************************************************************************/ #include "tscore/ink_defs.h" #include "P_EventSystem.h" +#include "swoc/Lexicon.h" + +#include // // General Buffer Allocator @@ -73,6 +76,80 @@ init_buffer_allocators(int iobuffer_advice) init_buffer_allocators(iobuffer_advice, chunk_sizes, false); } +auto +make_buffer_size_parser() +{ + return [l = swoc::Lexicon{ + {{0, {"128"}}, + {1, {"256"}}, + {2, {"512"}}, + {3, {"1k", "1024"}}, + {4, {"2k", "2048"}}, + {5, {"4k", "4096"}}, + {6, {"8k", "8192"}}, + {7, {"16k"}}, + {8, {"32k"}}, + {9, {"64k"}}, + {10, {"128k"}}, + {11, {"256k"}}, + {12, {"512k"}}, + {13, {"1M", "1024k"}}, + {14, {"2M", "2048k"}}}, + -1 + }](swoc::TextView esize) -> std::optional { + int result = l[esize]; + if (result == -1) { + return std::nullopt; + } + return result; + }; +} + +bool +parse_buffer_chunk_sizes(const char *chunk_sizes_string, int chunk_sizes[DEFAULT_BUFFER_SIZES]) +{ + const swoc::TextView delimiters(", "); + if (chunk_sizes_string != nullptr) { + swoc::TextView src(chunk_sizes_string, swoc::TextView::npos); + auto parser = make_buffer_size_parser(); + int n = 0; + while (!src.empty()) { + swoc::TextView token{src.take_prefix_at(delimiters)}; + + swoc::TextView esize = token.take_prefix_at(':'); + if (!token.empty()) { + auto parsed = parser(esize); + if (parsed) { + n = *parsed; + } else { + Error("Failed to parse size for %.*s", static_cast(esize.size()), esize.data()); + return false; + } + } else { + // element didn't have a colon so its just a chunk size + token = esize; + } + + // Check if n goes out of bounds + if (n >= DEFAULT_BUFFER_SIZES) { + Error("Invalid IO buffer chunk sizes string"); + return false; + } + + auto x = swoc::svto_radix<10>(token); + if (token.empty() && x != std::numeric_limits::max()) { + chunk_sizes[n++] = x; + } else { + Error("Failed to parse chunk size"); + return false; + } + + src.ltrim(delimiters); + } + } + return true; +} + // // MIOBuffer // diff --git a/iocore/eventsystem/I_IOBuffer.h b/iocore/eventsystem/I_IOBuffer.h index cdf1d8d1cdc..ee522e6d7b9 100644 --- a/iocore/eventsystem/I_IOBuffer.h +++ b/iocore/eventsystem/I_IOBuffer.h @@ -115,6 +115,8 @@ 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); +bool parse_buffer_chunk_sizes(const char *s, int chunk_sizes[DEFAULT_BUFFER_SIZES]); + /** A reference counted wrapper around fast allocated or malloced memory. The IOBufferData class provides two basic services around a portion diff --git a/iocore/eventsystem/unit_tests/test_IOBuffer.cc b/iocore/eventsystem/unit_tests/test_IOBuffer.cc index fe91e7e1822..4cc95d74348 100644 --- a/iocore/eventsystem/unit_tests/test_IOBuffer.cc +++ b/iocore/eventsystem/unit_tests/test_IOBuffer.cc @@ -330,6 +330,51 @@ TEST_CASE("MIOBuffer", "[iocore]") } } +TEST_CASE("block size parser", "[iocore]") +{ + int chunk_sizes[DEFAULT_BUFFER_SIZES] = {0}; + auto reset = [&]() { + for (auto &s : chunk_sizes) { + s = 0; + } + }; + + REQUIRE(parse_buffer_chunk_sizes("1 2,3, 4", chunk_sizes)); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_128] == 1); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_256] == 2); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_512] == 3); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_1K] == 4); + reset(); + + REQUIRE(parse_buffer_chunk_sizes("256k:1", chunk_sizes)); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_256K] == 1); + reset(); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_256K] == 0); + + REQUIRE(parse_buffer_chunk_sizes("1M:1 256k:2,256:5 2M:10", chunk_sizes)); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_1M] == 1); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_256K] == 2); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_256] == 5); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_2M] == 10); + reset(); + + REQUIRE(parse_buffer_chunk_sizes("2M:1 256k:2", chunk_sizes)); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_2M] == 1); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_256K] == 2); + reset(); + + // leaving out the index token will just move to the next spot + REQUIRE(parse_buffer_chunk_sizes("1M:1 2", chunk_sizes)); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_1M] == 1); + REQUIRE(chunk_sizes[TS_IOBUFFER_SIZE_INDEX_2M] == 2); + + // test can't go past the end + REQUIRE(parse_buffer_chunk_sizes("1M:1 2 3", chunk_sizes) == false); + + // bad index token + REQUIRE(parse_buffer_chunk_sizes("bob:1 2 3", chunk_sizes) == false); +} + struct EventProcessorListener : Catch::TestEventListenerBase { using TestEventListenerBase::TestEventListenerBase; diff --git a/iocore/hostdb/Makefile.am b/iocore/hostdb/Makefile.am index fcde4788baf..09ae1ee67bf 100644 --- a/iocore/hostdb/Makefile.am +++ b/iocore/hostdb/Makefile.am @@ -89,10 +89,7 @@ test_HostFile_CPPFLAGS = \ -I$(abs_top_srcdir)/tests/include \ -I$(abs_top_srcdir)/proxy/http/remap -test_HostFile_LDADD = \ - $(top_builddir)/src/tscore/libtscore.la \ - $(top_builddir)/src/tscpp/util/libtscpputil.la \ - $(top_builddir)/iocore/eventsystem/libinkevent.a +test_HostFile_LDADD = $(test_LD_ADD) test_HostFile_SOURCES = \ test_HostFile.cc \ diff --git a/proxy/logging/Makefile.am b/proxy/logging/Makefile.am index 2fd6d75cc6d..e0576e640d3 100644 --- a/proxy/logging/Makefile.am +++ b/proxy/logging/Makefile.am @@ -84,7 +84,8 @@ test_LogUtils_SOURCES = \ test_LogUtils_LDADD = \ $(top_builddir)/src/tscore/libtscore.la \ $(top_builddir)/src/tscpp/util/libtscpputil.la \ - $(top_builddir)/iocore/eventsystem/libinkevent.a + $(top_builddir)/iocore/eventsystem/libinkevent.a \ + @SWOC_LIBS@ @HWLOC_LIBS@ @YAMLCPP_LIBS@ test_RolledLogDeleter_CPPFLAGS = \ $(AM_CPPFLAGS) \ @@ -99,7 +100,8 @@ test_RolledLogDeleter_SOURCES = \ test_RolledLogDeleter_LDADD = \ $(top_builddir)/src/tscore/libtscore.la \ $(top_builddir)/src/tscpp/util/libtscpputil.la \ - $(top_builddir)/iocore/eventsystem/libinkevent.a + $(top_builddir)/iocore/eventsystem/libinkevent.a \ + @SWOC_LIBS@ @HWLOC_LIBS@ @YAMLCPP_LIBS@ clang-tidy-local: $(liblogging_a_SOURCES) $(EXTRA_DIST) $(CXX_Clang_Tidy) diff --git a/src/records/RecordsConfig.cc b/src/records/RecordsConfig.cc index 31317d76b4c..f1c06bf7b13 100644 --- a/src/records/RecordsConfig.cc +++ b/src/records/RecordsConfig.cc @@ -819,8 +819,6 @@ 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} @@ -1487,8 +1485,6 @@ static const RecordElement RecordsConfig[] = , {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/src/traffic_quic/Makefile.inc b/src/traffic_quic/Makefile.inc index 7649c8279d6..97e3ea9c10e 100644 --- a/src/traffic_quic/Makefile.inc +++ b/src/traffic_quic/Makefile.inc @@ -49,7 +49,7 @@ traffic_quic_traffic_quic_LDADD = \ $(top_builddir)/iocore/net/libinknet.a \ $(top_builddir)/iocore/aio/libinkaio.a \ $(top_builddir)/iocore/net/quic/libquic.a \ - $(top_builddir)/iocore/eventsystem/libinkevent.a \ + $(top_builddir)/iocore/eventsystem/libinkevent.a \ $(top_builddir)/src/records/librecords_p.a \ $(top_builddir)/src/tscore/libtscore.la \ $(top_builddir)/src/tscpp/util/libtscpputil.la \