You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2020/07/08 15:31:05 UTC

[trafficserver] 02/02: Customize Max IOBuffer Size (#6869)

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

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

commit 63f8d1d3da4601536bcfc8b79ee6c15093f338a4
Author: Sudheer Vinukonda <su...@apache.org>
AuthorDate: Thu Jun 18 18:23:35 2020 -0700

    Customize Max IOBuffer Size (#6869)
    
    * Customize Max IOBuffer Size.
    
    Allow callers explicitly configure and pass in the max buffer sizes
    when asking for unknown sized memory chunks depending on the usecase
    instead of relying on a common/global default config.
    
    - Remove proxy.config.io.max_buffer_size
    - Add docs for the new configs
    
    (cherry picked from commit 6239297fe7cf448915d41f2298f402e24520d896)
---
 doc/admin-guide/files/records.config.en.rst        | 25 ++++++++++++
 iocore/cache/CachePages.cc                         |  2 +-
 iocore/cache/CacheTest.cc                          |  4 +-
 iocore/eventsystem/EventSystem.cc                  | 13 +-----
 iocore/eventsystem/I_IOBuffer.h                    | 23 +++++------
 iocore/eventsystem/P_IOBuffer.h                    |  8 +---
 iocore/eventsystem/unit_tests/test_IOBuffer.cc     | 22 ++++------
 iocore/hostdb/HostDB.cc                            |  3 ++
 iocore/hostdb/I_HostDBProcessor.h                  |  4 +-
 iocore/net/NetVCTest.cc                            |  4 +-
 iocore/net/P_SSLConfig.h                           |  1 +
 iocore/net/P_SSLNetVConnection.h                   |  3 +-
 iocore/net/QUICNetVConnection.cc                   |  4 +-
 iocore/net/QUICPacketHandler.cc                    |  2 +-
 iocore/net/SSLConfig.cc                            |  3 ++
 iocore/net/SSLNextProtocolAccept.cc                |  5 ++-
 iocore/net/Socks.cc                                |  2 +-
 iocore/net/quic/QUICFrame.cc                       | 47 +++++++++++-----------
 iocore/net/quic/QUICPacketPayloadProtector.cc      |  4 +-
 iocore/net/quic/test/test_QUICFrame.cc             | 18 ++++-----
 iocore/net/quic/test/test_QUICFrameDispatcher.cc   |  2 +-
 .../net/quic/test/test_QUICFrameRetransmitter.cc   |  6 +--
 .../net/quic/test/test_QUICIncomingFrameBuffer.cc  | 12 +++---
 iocore/net/quic/test/test_QUICStreamManager.cc     | 10 ++---
 iocore/utils/OneWayMultiTunnel.cc                  |  4 +-
 iocore/utils/OneWayTunnel.cc                       |  4 +-
 mgmt/RecordsConfig.cc                              | 10 ++++-
 plugins/experimental/memcache/tsmemcache.cc        |  6 +--
 proxy/Transform.cc                                 |  8 ++--
 proxy/http/HttpConfig.cc                           |  4 ++
 proxy/http/HttpConfig.h                            |  3 ++
 proxy/http/HttpSM.cc                               | 20 ++++-----
 proxy/http/HttpTransact.cc                         |  5 ++-
 proxy/http2/unit_tests/test_Http2Frame.cc          |  2 +-
 proxy/http3/Http3HeaderFramer.cc                   |  2 +-
 proxy/http3/test/test_QPACK.cc                     |  2 +-
 proxy/logging/LogBuffer.cc                         |  4 +-
 proxy/logging/LogConfig.cc                         | 12 +++++-
 proxy/logging/LogConfig.h                          |  1 +
 src/traffic_quic/quic_client.cc                    |  4 +-
 src/traffic_server/InkAPITest.cc                   |  2 +-
 src/traffic_server/InkIOCoreAPI.cc                 |  2 +-
 src/traffic_server/SocksProxy.cc                   |  2 +-
 43 files changed, 180 insertions(+), 144 deletions(-)

diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst
index 6b87563..4299f5a 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -4392,6 +4392,31 @@ 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.ssl.misc.io.max_buffer_index INT 8
+
+   Configures the max IOBuffer Block index used for various SSL Operations
+   such as Handshake or Protocol Probe. Default value is 8 which maps to a 32K buffer
+
+.. ts:cv:: CONFIG proxy.config.hostdb.io.max_buffer_index INT 8
+
+   Configures the max IOBuffer Block index used for storing HostDB records.
+   Default value is 8 which maps to a 32K buffer
+
+.. ts:cv:: CONFIG proxy.config.payload.io.max_buffer_index INT 8
+
+   Configures the max IOBuffer Block index used for storing request payload buffer
+   for a POST request. Default value is 8 which maps to a 32K buffer
+
+.. ts:cv:: CONFIG proxy.config.msg.io.max_buffer_index INT 8
+
+   Configures the max IOBuffer Block index used for storing miscellaneous transactional
+   buffers such as error response body. Default value is 8 which maps to a 32K buffer
+
+.. ts:cv:: CONFIG proxy.config.log.io.max_buffer_index INT 8
+
+   Configures the max IOBuffer Block index used for storing an access log entry.
+   Default value is 8 which maps to a 32K buffer
+
 .. ts:cv:: CONFIG proxy.config.http.enabled INT 1
 
    Turn on or off support for HTTP proxying. This is rarely used, the one
diff --git a/iocore/cache/CachePages.cc b/iocore/cache/CachePages.cc
index 5f2930b..651499c 100644
--- a/iocore/cache/CachePages.cc
+++ b/iocore/cache/CachePages.cc
@@ -427,7 +427,7 @@ ShowCache::handleCacheEvent(int event, Event *e)
 
   case VC_EVENT_READ_READY:
     if (!cvio) {
-      buffer         = new_empty_MIOBuffer();
+      buffer         = new_empty_MIOBuffer(BUFFER_SIZE_INDEX_32K);
       buffer_reader  = buffer->alloc_reader();
       content_length = cache_vc->get_object_size();
       cvio           = cache_vc->do_io_read(this, content_length, buffer);
diff --git a/iocore/cache/CacheTest.cc b/iocore/cache/CacheTest.cc
index 79b33bd..d4f1b0c 100644
--- a/iocore/cache/CacheTest.cc
+++ b/iocore/cache/CacheTest.cc
@@ -95,7 +95,7 @@ CacheTestSM::event_handler(int event, void *data)
     cancel_timeout();
     cache_action  = nullptr;
     cache_vc      = static_cast<CacheVConnection *>(data);
-    buffer        = new_empty_MIOBuffer();
+    buffer        = new_empty_MIOBuffer(BUFFER_SIZE_INDEX_32K);
     buffer_reader = buffer->alloc_reader();
     if (open_read_callout() < 0) {
       goto Lclose_error_next;
@@ -129,7 +129,7 @@ CacheTestSM::event_handler(int event, void *data)
     cancel_timeout();
     cache_action  = nullptr;
     cache_vc      = static_cast<CacheVConnection *>(data);
-    buffer        = new_empty_MIOBuffer();
+    buffer        = new_empty_MIOBuffer(BUFFER_SIZE_INDEX_32K);
     buffer_reader = buffer->alloc_reader();
     if (open_write_callout() < 0) {
       goto Lclose_error_next;
diff --git a/iocore/eventsystem/EventSystem.cc b/iocore/eventsystem/EventSystem.cc
index f5d5dc0..1497177 100644
--- a/iocore/eventsystem/EventSystem.cc
+++ b/iocore/eventsystem/EventSystem.cc
@@ -34,8 +34,7 @@ void
 ink_event_system_init(ts::ModuleVersion v)
 {
   ink_release_assert(v.check(EVENT_SYSTEM_MODULE_INTERNAL_VERSION));
-  int config_max_iobuffer_size = DEFAULT_MAX_BUFFER_SIZE;
-  int iobuffer_advice          = 0;
+  int iobuffer_advice = 0;
 
   // For backwards compatibility make sure to allow thread_freelist_size
   // This needs to change in 6.0
@@ -43,16 +42,6 @@ ink_event_system_init(ts::ModuleVersion v)
 
   REC_EstablishStaticConfigInt32(thread_freelist_low_watermark, "proxy.config.allocator.thread_freelist_low_watermark");
 
-  REC_ReadConfigInteger(config_max_iobuffer_size, "proxy.config.io.max_buffer_size");
-
-  max_iobuffer_size = buffer_size_to_index(config_max_iobuffer_size, DEFAULT_BUFFER_SIZES - 1);
-  if (default_small_iobuffer_size > max_iobuffer_size) {
-    default_small_iobuffer_size = max_iobuffer_size;
-  }
-  if (default_large_iobuffer_size > max_iobuffer_size) {
-    default_large_iobuffer_size = max_iobuffer_size;
-  }
-
 #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);
diff --git a/iocore/eventsystem/I_IOBuffer.h b/iocore/eventsystem/I_IOBuffer.h
index 6173006..6440749 100644
--- a/iocore/eventsystem/I_IOBuffer.h
+++ b/iocore/eventsystem/I_IOBuffer.h
@@ -52,10 +52,6 @@ class MIOBuffer;
 class IOBufferReader;
 class VIO;
 
-inkcoreapi extern int64_t max_iobuffer_size;
-extern int64_t default_small_iobuffer_size;
-extern int64_t default_large_iobuffer_size; // matched to size of OS buffers
-
 enum AllocType {
   NO_ALLOC,
   MEMALIGNED,
@@ -417,7 +413,7 @@ public:
     section in MIOBuffer.
 
   */
-  void alloc(int64_t i = default_large_iobuffer_size);
+  void alloc(int64_t i);
 
   /**
     Clear the IOBufferData this IOBufferBlock handles. Clears this
@@ -1148,7 +1144,7 @@ public:
   void dealloc_all_readers();
 
   void set(void *b, int64_t len);
-  void alloc(int64_t i = default_large_iobuffer_size);
+  void alloc(int64_t i);
   void append_block_internal(IOBufferBlock *b);
   int64_t write(IOBufferBlock const *b, int64_t len, int64_t offset);
 
@@ -1290,7 +1286,7 @@ private:
   IOBufferReader *entry = nullptr;
 };
 
-extern MIOBuffer *new_MIOBuffer_internal(const char *loc, int64_t size_index = default_large_iobuffer_size);
+extern MIOBuffer *new_MIOBuffer_internal(const char *loc, int64_t size_index);
 
 class MIOBuffer_tracker
 {
@@ -1299,13 +1295,13 @@ class MIOBuffer_tracker
 public:
   explicit MIOBuffer_tracker(const char *_loc) : loc(_loc) {}
   MIOBuffer *
-  operator()(int64_t size_index = default_large_iobuffer_size)
+  operator()(int64_t size_index)
   {
     return new_MIOBuffer_internal(loc, size_index);
   }
 };
 
-extern MIOBuffer *new_empty_MIOBuffer_internal(const char *loc, int64_t size_index = default_large_iobuffer_size);
+extern MIOBuffer *new_empty_MIOBuffer_internal(const char *loc, int64_t size_index);
 
 class Empty_MIOBuffer_tracker
 {
@@ -1314,7 +1310,7 @@ class Empty_MIOBuffer_tracker
 public:
   explicit Empty_MIOBuffer_tracker(const char *_loc) : loc(_loc) {}
   MIOBuffer *
-  operator()(int64_t size_index = default_large_iobuffer_size)
+  operator()(int64_t size_index)
   {
     return new_empty_MIOBuffer_internal(loc, size_index);
   }
@@ -1352,8 +1348,7 @@ public:
 #define new_IOBufferBlock IOBufferBlock_tracker(RES_PATH("memory/IOBuffer/"))
 ////////////////////////////////////////////////////////////
 
-extern IOBufferData *new_IOBufferData_internal(const char *location, int64_t size_index = default_large_iobuffer_size,
-                                               AllocType type = DEFAULT_ALLOC);
+extern IOBufferData *new_IOBufferData_internal(const char *location, int64_t size_index, AllocType type = DEFAULT_ALLOC);
 
 extern IOBufferData *new_xmalloc_IOBufferData_internal(const char *location, void *b, int64_t size);
 
@@ -1364,7 +1359,7 @@ class IOBufferData_tracker
 public:
   explicit IOBufferData_tracker(const char *_loc) : loc(_loc) {}
   IOBufferData *
-  operator()(int64_t size_index = default_large_iobuffer_size, AllocType type = DEFAULT_ALLOC)
+  operator()(int64_t size_index, AllocType type = DEFAULT_ALLOC)
   {
     return new_IOBufferData_internal(loc, size_index, type);
   }
@@ -1374,7 +1369,7 @@ public:
 #define new_IOBufferData IOBufferData_tracker(RES_PATH("memory/IOBuffer/"))
 #define new_xmalloc_IOBufferData(b, size) new_xmalloc_IOBufferData_internal(RES_PATH("memory/IOBuffer/"), (b), (size))
 
-extern int64_t iobuffer_size_to_index(int64_t size, int64_t max = max_iobuffer_size);
+extern int64_t iobuffer_size_to_index(int64_t size, int64_t max);
 extern int64_t index_to_buffer_size(int64_t idx);
 /**
   Clone a IOBufferBlock chain. Used to snarf a IOBufferBlock chain
diff --git a/iocore/eventsystem/P_IOBuffer.h b/iocore/eventsystem/P_IOBuffer.h
index 00cd7f0..41e73f0 100644
--- a/iocore/eventsystem/P_IOBuffer.h
+++ b/iocore/eventsystem/P_IOBuffer.h
@@ -36,7 +36,7 @@
 //
 //////////////////////////////////////////////////////////////
 TS_INLINE int64_t
-buffer_size_to_index(int64_t size, int64_t max = max_iobuffer_size)
+buffer_size_to_index(int64_t size, int64_t max)
 {
   int64_t r = max;
 
@@ -215,12 +215,6 @@ new_xmalloc_IOBufferData_internal(const char *location, void *b, int64_t size)
 }
 
 TS_INLINE IOBufferData *
-new_IOBufferData_internal(const char *location, void *b, int64_t size)
-{
-  return new_IOBufferData_internal(location, b, size, iobuffer_size_to_index(size));
-}
-
-TS_INLINE IOBufferData *
 new_IOBufferData_internal(const char *loc, int64_t size_index, AllocType type)
 {
   IOBufferData *d = THREAD_ALLOC(ioDataAllocator, this_thread());
diff --git a/iocore/eventsystem/unit_tests/test_IOBuffer.cc b/iocore/eventsystem/unit_tests/test_IOBuffer.cc
index 8128ffb..1c2c407 100644
--- a/iocore/eventsystem/unit_tests/test_IOBuffer.cc
+++ b/iocore/eventsystem/unit_tests/test_IOBuffer.cc
@@ -35,26 +35,19 @@
 
 TEST_CASE("MIOBuffer", "[iocore]")
 {
-  // These value could be tweaked by `ink_event_system_init()` using `proxy.config.io.max_buffer_size`
-  REQUIRE(default_small_iobuffer_size == DEFAULT_SMALL_BUFFER_SIZE);
-  REQUIRE(default_large_iobuffer_size == DEFAULT_LARGE_BUFFER_SIZE);
-
-  REQUIRE(BUFFER_SIZE_FOR_INDEX(default_small_iobuffer_size) == 512);
-  REQUIRE(BUFFER_SIZE_FOR_INDEX(default_large_iobuffer_size) == 4096);
-
   SECTION("new_MIOBuffer 100 times")
   {
     int64_t read_avail_len1 = 0;
     int64_t read_avail_len2 = 0;
 
     for (unsigned i = 0; i < 100; ++i) {
-      MIOBuffer *b1            = new_MIOBuffer(default_small_iobuffer_size);
+      MIOBuffer *b1            = new_MIOBuffer(BUFFER_SIZE_INDEX_512);
       int64_t len1             = b1->write_avail();
       IOBufferReader *b1reader = b1->alloc_reader();
       b1->fill(len1);
       read_avail_len1 += b1reader->read_avail();
 
-      MIOBuffer *b2            = new_MIOBuffer(default_large_iobuffer_size);
+      MIOBuffer *b2            = new_MIOBuffer(BUFFER_SIZE_INDEX_4K);
       int64_t len2             = b2->write_avail();
       IOBufferReader *b2reader = b2->alloc_reader();
       b2->fill(len2);
@@ -64,19 +57,19 @@ TEST_CASE("MIOBuffer", "[iocore]")
       free_MIOBuffer(b1);
     }
 
-    CHECK(read_avail_len1 == 100 * BUFFER_SIZE_FOR_INDEX(default_small_iobuffer_size));
-    CHECK(read_avail_len2 == 100 * BUFFER_SIZE_FOR_INDEX(default_large_iobuffer_size));
+    CHECK(read_avail_len1 == 100 * BUFFER_SIZE_FOR_INDEX(BUFFER_SIZE_INDEX_512));
+    CHECK(read_avail_len2 == 100 * BUFFER_SIZE_FOR_INDEX(BUFFER_SIZE_INDEX_4K));
   }
 
   SECTION("write")
   {
-    MIOBuffer *miob            = new_MIOBuffer();
+    MIOBuffer *miob            = new_MIOBuffer(BUFFER_SIZE_INDEX_4K);
     IOBufferReader *miob_r     = miob->alloc_reader();
     const IOBufferBlock *block = miob->first_write_block();
 
     SECTION("initial state")
     {
-      CHECK(miob->size_index == default_large_iobuffer_size);
+      CHECK(miob->size_index == BUFFER_SIZE_INDEX_4K);
       CHECK(miob->water_mark == 0);
       CHECK(miob->first_write_block() != nullptr);
       CHECK(miob->block_size() == 4096);
@@ -176,7 +169,7 @@ TEST_CASE("MIOBuffer", "[iocore]")
 
   SECTION("write_avail")
   {
-    MIOBuffer *miob        = new_MIOBuffer();
+    MIOBuffer *miob        = new_MIOBuffer(BUFFER_SIZE_INDEX_4K);
     IOBufferReader *miob_r = miob->alloc_reader();
     uint8_t buf[8192];
     memset(buf, 0xAA, sizeof(buf));
@@ -347,7 +340,6 @@ struct EventProcessorListener : Catch::TestEventListenerBase {
     init_diags("", nullptr);
     RecProcessInit(RECM_STAND_ALONE);
 
-    // Initialize LibRecordsConfig for `proxy.config.io.max_buffer_size` (32K)
     LibRecordsConfigInit();
 
     ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION);
diff --git a/iocore/hostdb/HostDB.cc b/iocore/hostdb/HostDB.cc
index 555ea95..f06a39c 100644
--- a/iocore/hostdb/HostDB.cc
+++ b/iocore/hostdb/HostDB.cc
@@ -62,6 +62,7 @@ int hostdb_max_count                               = DEFAULT_HOST_DB_SIZE;
 char hostdb_hostfile_path[PATH_NAME_MAX]           = "";
 int hostdb_sync_frequency                          = 0;
 int hostdb_disable_reverse_lookup                  = 0;
+int hostdb_max_iobuf_index                         = BUFFER_SIZE_INDEX_32K;
 
 ClassAllocator<HostDBContinuation> hostDBContAllocator("hostDBContAllocator");
 
@@ -325,6 +326,8 @@ HostDBCache::start(int flags)
   // how often to sync hostdb to disk
   REC_EstablishStaticConfigInt32(hostdb_sync_frequency, "proxy.config.cache.hostdb.sync_frequency");
 
+  REC_EstablishStaticConfigInt32(hostdb_max_iobuf_index, "proxy.config.hostdb.io.max_buffer_index");
+
   if (hostdb_max_size == 0) {
     Fatal("proxy.config.hostdb.max_size must be a non-zero number");
   }
diff --git a/iocore/hostdb/I_HostDBProcessor.h b/iocore/hostdb/I_HostDBProcessor.h
index 3d15faf..fbf068a 100644
--- a/iocore/hostdb/I_HostDBProcessor.h
+++ b/iocore/hostdb/I_HostDBProcessor.h
@@ -62,6 +62,8 @@ extern unsigned int hostdb_ip_fail_timeout_interval;
 extern unsigned int hostdb_serve_stale_but_revalidate;
 extern unsigned int hostdb_round_robin_max_count;
 
+extern int hostdb_max_iobuf_index;
+
 static inline unsigned int
 makeHostHash(const char *string)
 {
@@ -146,7 +148,7 @@ struct HostDBInfo : public RefCountObj {
   alloc(int size = 0)
   {
     size += sizeof(HostDBInfo);
-    int iobuffer_index = iobuffer_size_to_index(size);
+    int iobuffer_index = iobuffer_size_to_index(size, hostdb_max_iobuf_index);
     ink_release_assert(iobuffer_index >= 0);
     void *ptr = ioBufAllocator[iobuffer_index].alloc_void();
     memset(ptr, 0, size);
diff --git a/iocore/net/NetVCTest.cc b/iocore/net/NetVCTest.cc
index 5d3eaa9..59a066b 100644
--- a/iocore/net/NetVCTest.cc
+++ b/iocore/net/NetVCTest.cc
@@ -138,8 +138,8 @@ NetVCTest::start_test()
   test_vc->set_inactivity_timeout(HRTIME_SECONDS(timeout));
   test_vc->set_active_timeout(HRTIME_SECONDS(timeout + 5));
 
-  read_buffer  = new_MIOBuffer();
-  write_buffer = new_MIOBuffer();
+  read_buffer  = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
+  write_buffer = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
 
   reader_for_rbuf = read_buffer->alloc_reader();
   reader_for_wbuf = write_buffer->alloc_reader();
diff --git a/iocore/net/P_SSLConfig.h b/iocore/net/P_SSLConfig.h
index c11f20b..382cd07 100644
--- a/iocore/net/P_SSLConfig.h
+++ b/iocore/net/P_SSLConfig.h
@@ -108,6 +108,7 @@ struct SSLConfigParams : public ConfigInfo {
   static bool server_allow_early_data_params;
 
   static int ssl_maxrecord;
+  static int ssl_misc_max_iobuffer_size_index;
   static bool ssl_allow_client_renegotiation;
 
   static bool ssl_ocsp_enabled;
diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h
index 4254805..c059e75 100644
--- a/iocore/net/P_SSLNetVConnection.h
+++ b/iocore/net/P_SSLNetVConnection.h
@@ -49,6 +49,7 @@
 #include "P_ALPNSupport.h"
 #include "TLSSessionResumptionSupport.h"
 #include "P_SSLUtils.h"
+#include "P_SSLConfig.h"
 
 // These are included here because older OpenSSL libraries don't have them.
 // Don't copy these defines, or use their values directly, they are merely
@@ -182,7 +183,7 @@ public:
   void
   initialize_handshake_buffers()
   {
-    this->handShakeBuffer    = new_MIOBuffer();
+    this->handShakeBuffer    = new_MIOBuffer(SSLConfigParams::ssl_misc_max_iobuffer_size_index);
     this->handShakeReader    = this->handShakeBuffer->alloc_reader();
     this->handShakeHolder    = this->handShakeReader->clone();
     this->handShakeBioStored = 0;
diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc
index 9c4aa9d..004867d 100644
--- a/iocore/net/QUICNetVConnection.cc
+++ b/iocore/net/QUICNetVConnection.cc
@@ -1344,7 +1344,7 @@ QUICNetVConnection::_state_common_send_packet()
 
     Ptr<IOBufferBlock> udp_payload(new_IOBufferBlock());
     uint32_t udp_payload_len = std::min(window, this->_pmtu);
-    udp_payload->alloc(iobuffer_size_to_index(udp_payload_len));
+    udp_payload->alloc(iobuffer_size_to_index(udp_payload_len, BUFFER_SIZE_INDEX_32K));
 
     uint32_t written = 0;
     for (int i = static_cast<int>(this->_minimum_encryption_level); i <= static_cast<int>(QUICEncryptionLevel::ONE_RTT); ++i) {
@@ -1499,7 +1499,7 @@ QUICNetVConnection::_packetize_frames(QUICEncryptionLevel level, uint64_t max_pa
   size_t len                     = 0;
   Ptr<IOBufferBlock> first_block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
   Ptr<IOBufferBlock> last_block  = first_block;
-  first_block->alloc(iobuffer_size_to_index(0));
+  first_block->alloc(iobuffer_size_to_index(0, BUFFER_SIZE_INDEX_32K));
   first_block->fill(0);
 
   uint32_t seq_num   = this->_seq_num++;
diff --git a/iocore/net/QUICPacketHandler.cc b/iocore/net/QUICPacketHandler.cc
index 230acbb..9afee71 100644
--- a/iocore/net/QUICPacketHandler.cc
+++ b/iocore/net/QUICPacketHandler.cc
@@ -76,7 +76,7 @@ QUICPacketHandler::_send_packet(const QUICPacket &packet, UDPConnection *udp_con
 {
   size_t udp_len;
   Ptr<IOBufferBlock> udp_payload(new_IOBufferBlock());
-  udp_payload->alloc(iobuffer_size_to_index(pmtu));
+  udp_payload->alloc(iobuffer_size_to_index(pmtu, BUFFER_SIZE_INDEX_32K));
   packet.store(reinterpret_cast<uint8_t *>(udp_payload->end()), &udp_len);
   udp_payload->fill(udp_len);
 
diff --git a/iocore/net/SSLConfig.cc b/iocore/net/SSLConfig.cc
index d96cf80..51600fa 100644
--- a/iocore/net/SSLConfig.cc
+++ b/iocore/net/SSLConfig.cc
@@ -52,6 +52,7 @@ int SSLConfig::configid                                     = 0;
 int SSLCertificateConfig::configid                          = 0;
 int SSLTicketKeyConfig::configid                            = 0;
 int SSLConfigParams::ssl_maxrecord                          = 0;
+int SSLConfigParams::ssl_misc_max_iobuffer_size_index       = 8;
 bool SSLConfigParams::ssl_allow_client_renegotiation        = false;
 bool SSLConfigParams::ssl_ocsp_enabled                      = false;
 int SSLConfigParams::ssl_ocsp_cache_timeout                 = 3600;
@@ -452,6 +453,8 @@ SSLConfigParams::initialize()
 
   REC_ReadConfigInt32(ssl_allow_client_renegotiation, "proxy.config.ssl.allow_client_renegotiation");
 
+  REC_ReadConfigInt32(ssl_misc_max_iobuffer_size_index, "proxy.config.ssl.misc.io.max_buffer_index");
+
   // Enable client regardless of config file settings as remap file
   // can cause HTTP layer to connect using SSL. But only if SSL
   // initialization hasn't failed already.
diff --git a/iocore/net/SSLNextProtocolAccept.cc b/iocore/net/SSLNextProtocolAccept.cc
index 942bf02..dc21c49 100644
--- a/iocore/net/SSLNextProtocolAccept.cc
+++ b/iocore/net/SSLNextProtocolAccept.cc
@@ -166,7 +166,10 @@ SSLNextProtocolAccept::enableProtocols(const SessionProtocolSet &protos)
 }
 
 SSLNextProtocolAccept::SSLNextProtocolAccept(Continuation *ep, bool transparent_passthrough)
-  : SessionAccept(nullptr), buffer(new_empty_MIOBuffer()), endpoint(ep), transparent_passthrough(transparent_passthrough)
+  : SessionAccept(nullptr),
+    buffer(new_empty_MIOBuffer(SSLConfigParams::ssl_misc_max_iobuffer_size_index)),
+    endpoint(ep),
+    transparent_passthrough(transparent_passthrough)
 {
   SET_HANDLER(&SSLNextProtocolAccept::mainEvent);
 }
diff --git a/iocore/net/Socks.cc b/iocore/net/Socks.cc
index 7771abf..24964aa 100644
--- a/iocore/net/Socks.cc
+++ b/iocore/net/Socks.cc
@@ -44,7 +44,7 @@ void
 SocksEntry::init(Ptr<ProxyMutex> &m, SocksNetVC *vc, unsigned char socks_support, unsigned char ver)
 {
   mutex  = m;
-  buf    = new_MIOBuffer();
+  buf    = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
   reader = buf->alloc_reader();
 
   socks_cmd = socks_support;
diff --git a/iocore/net/quic/QUICFrame.cc b/iocore/net/quic/QUICFrame.cc
index 0c4e0ba..68f03e3 100644
--- a/iocore/net/quic/QUICFrame.cc
+++ b/iocore/net/quic/QUICFrame.cc
@@ -199,7 +199,7 @@ QUICStreamFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet)
 
   this->_valid = true;
   this->_block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  this->_block->alloc();
+  this->_block->alloc(BUFFER_SIZE_INDEX_32K);
   ink_assert(static_cast<uint64_t>(this->_block->write_avail()) > data_len);
   memcpy(this->_block->start(), pos, data_len);
   this->_block->fill(data_len);
@@ -279,7 +279,7 @@ QUICStreamFrame::to_io_buffer_block(size_t limit) const
   // Create header block
   size_t written_len = 0;
   header             = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  header->alloc(iobuffer_size_to_index(MAX_HEADER_SIZE));
+  header->alloc(iobuffer_size_to_index(MAX_HEADER_SIZE, BUFFER_SIZE_INDEX_32K));
   this->_store_header(reinterpret_cast<uint8_t *>(header->start()), &written_len, true);
   header->fill(written_len);
 
@@ -426,7 +426,7 @@ QUICCryptoFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet)
 
   this->_valid = true;
   this->_block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  this->_block->alloc();
+  this->_block->alloc(BUFFER_SIZE_INDEX_32K);
   ink_assert(static_cast<uint64_t>(this->_block->write_avail()) > data_len);
   memcpy(this->_block->start(), pos, data_len);
   this->_block->fill(data_len);
@@ -487,7 +487,7 @@ QUICCryptoFrame::to_io_buffer_block(size_t limit) const
   // Create header block
   size_t written_len = 0;
   header             = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  header->alloc(iobuffer_size_to_index(MAX_HEADER_SIZE));
+  header->alloc(iobuffer_size_to_index(MAX_HEADER_SIZE, BUFFER_SIZE_INDEX_32K));
   this->_store_header(reinterpret_cast<uint8_t *>(header->start()), &written_len);
   header->fill(written_len);
 
@@ -682,7 +682,7 @@ QUICAckFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + 24));
+  block->alloc(iobuffer_size_to_index(1 + 24, BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -855,7 +855,7 @@ QUICAckFrame::AckBlockSection::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(limit));
+  block->alloc(iobuffer_size_to_index(limit, BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   QUICIntUtil::write_QUICVariableInt(this->_first_ack_block, block_start + n, &written_len);
@@ -1076,7 +1076,7 @@ QUICRstStreamFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + 24));
+  block->alloc(iobuffer_size_to_index(1 + 24, BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -1165,7 +1165,7 @@ QUICPingFrame::to_io_buffer_block(size_t limit) const
   }
 
   block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(this->size()));
+  block->alloc(iobuffer_size_to_index(this->size(), BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -1231,7 +1231,7 @@ QUICPaddingFrame::to_io_buffer_block(size_t limit) const
   }
 
   block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(this->_size));
+  block->alloc(iobuffer_size_to_index(this->_size, BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   memset(block_start, 0, this->_size);
@@ -1377,7 +1377,7 @@ QUICConnectionCloseFrame::to_io_buffer_block(size_t limit) const
   // Create a block for Error Code(i) and Frame Type(i)
   size_t written_len = 0;
   first_block        = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  first_block->alloc(iobuffer_size_to_index(1 + 24));
+  first_block->alloc(iobuffer_size_to_index(1 + 24, BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(first_block->start());
 
   // Type
@@ -1406,7 +1406,7 @@ QUICConnectionCloseFrame::to_io_buffer_block(size_t limit) const
   if (this->_reason_phrase_length != 0) {
     // Reason Phrase (*)
     Ptr<IOBufferBlock> reason_block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-    reason_block->alloc(iobuffer_size_to_index(this->_reason_phrase_length));
+    reason_block->alloc(iobuffer_size_to_index(this->_reason_phrase_length, BUFFER_SIZE_INDEX_32K));
     memcpy(reinterpret_cast<uint8_t *>(reason_block->start()), this->_reason_phrase, this->_reason_phrase_length);
     reason_block->fill(this->_reason_phrase_length);
 
@@ -1538,7 +1538,7 @@ QUICMaxDataFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + sizeof(size_t)));
+  block->alloc(iobuffer_size_to_index(1 + sizeof(size_t), BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -1643,7 +1643,7 @@ QUICMaxStreamDataFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + sizeof(uint64_t) + sizeof(size_t)));
+  block->alloc(iobuffer_size_to_index(1 + sizeof(uint64_t) + sizeof(size_t), BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -1751,7 +1751,7 @@ QUICMaxStreamsFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + sizeof(size_t)));
+  block->alloc(iobuffer_size_to_index(1 + sizeof(size_t), BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -1842,7 +1842,7 @@ QUICDataBlockedFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + sizeof(size_t)));
+  block->alloc(iobuffer_size_to_index(1 + sizeof(size_t), BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -1940,7 +1940,7 @@ QUICStreamDataBlockedFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + sizeof(size_t)));
+  block->alloc(iobuffer_size_to_index(1 + sizeof(size_t), BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -2036,7 +2036,7 @@ QUICStreamIdBlockedFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + sizeof(size_t)));
+  block->alloc(iobuffer_size_to_index(1 + sizeof(size_t), BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -2155,7 +2155,8 @@ QUICNewConnectionIdFrame::to_io_buffer_block(size_t limit) const
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
   block->alloc(iobuffer_size_to_index(1 + sizeof(uint64_t) + sizeof(uint64_t) + 1 + QUICConnectionId::MAX_LENGTH +
-                                      QUICStatelessResetToken::LEN));
+                                        QUICStatelessResetToken::LEN,
+                                      BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -2301,7 +2302,7 @@ QUICStopSendingFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + 24));
+  block->alloc(iobuffer_size_to_index(1 + 24, BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -2402,7 +2403,7 @@ QUICPathChallengeFrame::to_io_buffer_block(size_t limit) const
   }
 
   block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + QUICPathChallengeFrame::DATA_LEN));
+  block->alloc(iobuffer_size_to_index(1 + QUICPathChallengeFrame::DATA_LEN, BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -2461,7 +2462,7 @@ QUICPathResponseFrame::to_io_buffer_block(size_t limit) const
   }
 
   block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + QUICPathResponseFrame::DATA_LEN));
+  block->alloc(iobuffer_size_to_index(1 + QUICPathResponseFrame::DATA_LEN, BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -2597,7 +2598,7 @@ QUICNewTokenFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + 24));
+  block->alloc(iobuffer_size_to_index(1 + 24, BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
@@ -2694,7 +2695,7 @@ QUICRetireConnectionIdFrame::to_io_buffer_block(size_t limit) const
 
   size_t written_len = 0;
   block              = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc(iobuffer_size_to_index(1 + sizeof(uint64_t)));
+  block->alloc(iobuffer_size_to_index(1 + sizeof(uint64_t), BUFFER_SIZE_INDEX_32K));
   uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());
 
   // Type
diff --git a/iocore/net/quic/QUICPacketPayloadProtector.cc b/iocore/net/quic/QUICPacketPayloadProtector.cc
index ca69057..374480b 100644
--- a/iocore/net/quic/QUICPacketPayloadProtector.cc
+++ b/iocore/net/quic/QUICPacketPayloadProtector.cc
@@ -47,7 +47,7 @@ QUICPacketPayloadProtector::protect(const Ptr<IOBufferBlock> unprotected_header,
   const EVP_CIPHER *cipher = this->_pp_key_info.get_cipher(phase);
 
   protected_payload = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  protected_payload->alloc(iobuffer_size_to_index(unprotected_payload->size() + tag_len));
+  protected_payload->alloc(iobuffer_size_to_index(unprotected_payload->size() + tag_len, BUFFER_SIZE_INDEX_32K));
 
   size_t written_len = 0;
   if (!this->_protect(reinterpret_cast<uint8_t *>(protected_payload->start()), written_len, protected_payload->write_avail(),
@@ -80,7 +80,7 @@ QUICPacketPayloadProtector::unprotect(const Ptr<IOBufferBlock> unprotected_heade
   const EVP_CIPHER *cipher = this->_pp_key_info.get_cipher(phase);
 
   unprotected_payload = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  unprotected_payload->alloc(iobuffer_size_to_index(protected_payload->size()));
+  unprotected_payload->alloc(iobuffer_size_to_index(protected_payload->size(), BUFFER_SIZE_INDEX_32K));
 
   size_t written_len = 0;
   if (!this->_unprotect(reinterpret_cast<uint8_t *>(unprotected_payload->start()), written_len, unprotected_payload->write_avail(),
diff --git a/iocore/net/quic/test/test_QUICFrame.cc b/iocore/net/quic/test/test_QUICFrame.cc
index 58f68e4..4460066 100644
--- a/iocore/net/quic/test/test_QUICFrame.cc
+++ b/iocore/net/quic/test/test_QUICFrame.cc
@@ -197,7 +197,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
 
     uint8_t raw1[]           = "\x01\x02\x03\x04\x05";
     Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-    block->alloc();
+    block->alloc(BUFFER_SIZE_INDEX_32K);
     memcpy(block->start(), raw1, 5);
     block->fill(5);
 
@@ -226,7 +226,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     };
     uint8_t raw2[]           = "\x01\x02\x03\x04\x05";
     Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-    block->alloc();
+    block->alloc(BUFFER_SIZE_INDEX_32K);
     memcpy(block->start(), raw2, 5);
     block->fill(5);
 
@@ -255,7 +255,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     };
     uint8_t raw3[]           = "\x01\x02\x03\x04\x05";
     Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-    block->alloc();
+    block->alloc(BUFFER_SIZE_INDEX_32K);
     memcpy(block->start(), raw3, 5);
     block->fill(5);
 
@@ -284,7 +284,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     };
     uint8_t raw4[]           = "\x01\x02\x03\x04\x05";
     Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-    block->alloc();
+    block->alloc(BUFFER_SIZE_INDEX_32K);
     memcpy(block->start(), raw4, 5);
     block->fill(5);
 
@@ -313,7 +313,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     };
     uint8_t raw5[]           = "\x01\x02\x03\x04\x05";
     Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-    block->alloc();
+    block->alloc(BUFFER_SIZE_INDEX_32K);
     memcpy(block->start(), raw5, 5);
     block->fill(5);
 
@@ -342,7 +342,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     };
     uint8_t raw6[]           = "\x01\x02\x03\x04\x05";
     Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-    block->alloc();
+    block->alloc(BUFFER_SIZE_INDEX_32K);
     memcpy(block->start(), raw6, 5);
     block->fill(5);
 
@@ -371,7 +371,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     };
     uint8_t raw7[]           = "\x01\x02\x03\x04\x05";
     Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-    block->alloc();
+    block->alloc(BUFFER_SIZE_INDEX_32K);
     memcpy(block->start(), raw7, 5);
     block->fill(5);
 
@@ -400,7 +400,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     };
     uint8_t raw[]            = "\x01\x02\x03\x04\x05";
     Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-    block->alloc();
+    block->alloc(BUFFER_SIZE_INDEX_32K);
     memcpy(block->start(), raw, 5);
     block->fill(5);
 
@@ -461,7 +461,7 @@ TEST_CASE("CRYPTO Frame", "[quic]")
     };
     uint8_t raw_data[]       = "\x01\x02\x03\x04\x05";
     Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-    block->alloc();
+    block->alloc(BUFFER_SIZE_INDEX_32K);
     memcpy(block->start(), raw_data, 5);
     block->fill(5);
 
diff --git a/iocore/net/quic/test/test_QUICFrameDispatcher.cc b/iocore/net/quic/test/test_QUICFrameDispatcher.cc
index eb89aa7..e34322b 100644
--- a/iocore/net/quic/test/test_QUICFrameDispatcher.cc
+++ b/iocore/net/quic/test/test_QUICFrameDispatcher.cc
@@ -30,7 +30,7 @@
 TEST_CASE("QUICFrameHandler", "[quic]")
 {
   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc();
+  block->alloc(BUFFER_SIZE_INDEX_32K);
   block->fill(1);
   CHECK(block->read_avail() == 1);
 
diff --git a/iocore/net/quic/test/test_QUICFrameRetransmitter.cc b/iocore/net/quic/test/test_QUICFrameRetransmitter.cc
index 39d50b7..c8a91a5 100644
--- a/iocore/net/quic/test/test_QUICFrameRetransmitter.cc
+++ b/iocore/net/quic/test/test_QUICFrameRetransmitter.cc
@@ -71,7 +71,7 @@ TEST_CASE("QUICFrameRetransmitter successfully create retransmitted frame", "[qu
   info->level                   = QUICEncryptionLevel::INITIAL;
 
   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc();
+  block->alloc(BUFFER_SIZE_INDEX_32K);
   memcpy(block->start(), data, sizeof(data));
   block->fill(sizeof(data));
 
@@ -96,7 +96,7 @@ TEST_CASE("QUICFrameRetransmitter successfully create stream frame", "[quic]")
   info->level                   = QUICEncryptionLevel::INITIAL;
 
   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc();
+  block->alloc(BUFFER_SIZE_INDEX_32K);
   memcpy(block->start(), data, sizeof(data));
   block->fill(sizeof(data));
 
@@ -132,7 +132,7 @@ TEST_CASE("QUICFrameRetransmitter successfully split stream frame", "[quic]")
   info->level                   = QUICEncryptionLevel::INITIAL;
 
   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc();
+  block->alloc(BUFFER_SIZE_INDEX_32K);
   memcpy(block->start(), data, sizeof(data));
   block->fill(sizeof(data));
 
diff --git a/iocore/net/quic/test/test_QUICIncomingFrameBuffer.cc b/iocore/net/quic/test/test_QUICIncomingFrameBuffer.cc
index 3b4e8a9..33dcbe7 100644
--- a/iocore/net/quic/test/test_QUICIncomingFrameBuffer.cc
+++ b/iocore/net/quic/test/test_QUICIncomingFrameBuffer.cc
@@ -35,12 +35,12 @@ TEST_CASE("QUICIncomingStreamFrameBuffer_fin_offset", "[quic]")
   QUICErrorUPtr err = nullptr;
 
   Ptr<IOBufferBlock> block_1024 = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block_1024->alloc();
+  block_1024->alloc(BUFFER_SIZE_INDEX_32K);
   block_1024->fill(1024);
   CHECK(block_1024->read_avail() == 1024);
 
   Ptr<IOBufferBlock> block_0 = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block_0->alloc();
+  block_0->alloc(BUFFER_SIZE_INDEX_32K);
   CHECK(block_0->read_avail() == 0);
 
   SECTION("single frame")
@@ -127,12 +127,12 @@ TEST_CASE("QUICIncomingStreamFrameBuffer_pop", "[quic]")
   QUICErrorUPtr err = nullptr;
 
   Ptr<IOBufferBlock> block_1024 = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block_1024->alloc();
+  block_1024->alloc(BUFFER_SIZE_INDEX_32K);
   block_1024->fill(1024);
   CHECK(block_1024->read_avail() == 1024);
 
   Ptr<IOBufferBlock> block_0 = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block_0->alloc();
+  block_0->alloc(BUFFER_SIZE_INDEX_32K);
   CHECK(block_0->read_avail() == 0);
 
   uint8_t frame_buf0[QUICFrame::MAX_INSTANCE_SIZE];
@@ -209,12 +209,12 @@ TEST_CASE("QUICIncomingStreamFrameBuffer_dup_frame", "[quic]")
   QUICErrorUPtr err = nullptr;
 
   Ptr<IOBufferBlock> block_1024 = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block_1024->alloc();
+  block_1024->alloc(BUFFER_SIZE_INDEX_32K);
   block_1024->fill(1024);
   CHECK(block_1024->read_avail() == 1024);
 
   Ptr<IOBufferBlock> block_0 = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block_0->alloc();
+  block_0->alloc(BUFFER_SIZE_INDEX_32K);
   CHECK(block_0->read_avail() == 0);
 
   uint8_t frame_buf0[QUICFrame::MAX_INSTANCE_SIZE];
diff --git a/iocore/net/quic/test/test_QUICStreamManager.cc b/iocore/net/quic/test/test_QUICStreamManager.cc
index 74a37cc..b875c79 100644
--- a/iocore/net/quic/test/test_QUICStreamManager.cc
+++ b/iocore/net/quic/test/test_QUICStreamManager.cc
@@ -62,7 +62,7 @@ TEST_CASE("QUICStreamManager_NewStream", "[quic]")
 
   // STREAM frames create new streams
   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc();
+  block->alloc(BUFFER_SIZE_INDEX_32K);
   block->fill(4);
   CHECK(block->read_avail() == 4);
 
@@ -119,7 +119,7 @@ TEST_CASE("QUICStreamManager_first_initial_map", "[quic]")
 
   // STREAM frames create new streams
   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc();
+  block->alloc(BUFFER_SIZE_INDEX_32K);
   block->fill(4);
   CHECK(block->read_avail() == 4);
 
@@ -178,7 +178,7 @@ TEST_CASE("QUICStreamManager_total_offset_received", "[quic]")
 
   // total_offset should be a integer in unit of 1024 octets
   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block->alloc();
+  block->alloc(BUFFER_SIZE_INDEX_32K);
   block->fill(1024);
   CHECK(block->read_avail() == 1024);
 
@@ -226,7 +226,7 @@ TEST_CASE("QUICStreamManager_total_offset_sent", "[quic]")
 
   // Create a stream with STREAM_DATA_BLOCKED (== noop)
   Ptr<IOBufferBlock> block_3 = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block_3->alloc();
+  block_3->alloc(BUFFER_SIZE_INDEX_32K);
   block_3->fill(3);
   CHECK(block_3->read_avail() == 3);
 
@@ -240,7 +240,7 @@ TEST_CASE("QUICStreamManager_total_offset_sent", "[quic]")
   CHECK(sm.total_offset_sent() == 0);
 
   Ptr<IOBufferBlock> block_1024 = make_ptr<IOBufferBlock>(new_IOBufferBlock());
-  block_1024->alloc();
+  block_1024->alloc(BUFFER_SIZE_INDEX_32K);
   block_1024->fill(1024);
   CHECK(block_1024->read_avail() == 1024);
 
diff --git a/iocore/utils/OneWayMultiTunnel.cc b/iocore/utils/OneWayMultiTunnel.cc
index 3b8830a..2a3f878 100644
--- a/iocore/utils/OneWayMultiTunnel.cc
+++ b/iocore/utils/OneWayMultiTunnel.cc
@@ -64,9 +64,9 @@ OneWayMultiTunnel::init(VConnection *vcSource, VConnection **vcTargets, int n_vc
 
   int64_t size_index = 0;
   if (size_estimate) {
-    size_index = buffer_size_to_index(size_estimate, default_large_iobuffer_size);
+    size_index = buffer_size_to_index(size_estimate, BUFFER_SIZE_INDEX_32K);
   } else {
-    size_index = default_large_iobuffer_size;
+    size_index = BUFFER_SIZE_INDEX_32K;
   }
 
   tunnel_till_done = (nbytes == TUNNEL_TILL_DONE);
diff --git a/iocore/utils/OneWayTunnel.cc b/iocore/utils/OneWayTunnel.cc
index c2238b4..b2ac187 100644
--- a/iocore/utils/OneWayTunnel.cc
+++ b/iocore/utils/OneWayTunnel.cc
@@ -126,9 +126,9 @@ OneWayTunnel::init(VConnection *vcSource, VConnection *vcTarget, Continuation *a
   int64_t size_index = 0;
 
   if (size_estimate) {
-    size_index = buffer_size_to_index(size_estimate);
+    size_index = buffer_size_to_index(size_estimate, BUFFER_SIZE_INDEX_32K);
   } else {
-    size_index = default_large_iobuffer_size;
+    size_index = BUFFER_SIZE_INDEX_32K;
   }
 
   Debug("one_way_tunnel", "buffer size index [%" PRId64 "] [%d]", size_index, size_estimate);
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index 6689252..a3c4d10 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -718,7 +718,15 @@ static const RecordElement RecordsConfig[] =
   //# I/O Subsystem
   //#
   //##############################################################################
-  {RECT_CONFIG, "proxy.config.io.max_buffer_size", RECD_INT, "32768", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  {RECT_CONFIG, "proxy.config.ssl.misc.io.max_buffer_index", RECD_INT, "8", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
+  {RECT_CONFIG, "proxy.config.hostdb.io.max_buffer_index", RECD_INT, "8", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
+  {RECT_CONFIG, "proxy.config.payload.io.max_buffer_index", RECD_INT, "8", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
+  {RECT_CONFIG, "proxy.config.msg.io.max_buffer_index", RECD_INT, "8", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
+  {RECT_CONFIG, "proxy.config.log.io.max_buffer_index", RECD_INT, "8", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
   ,
 
   //##############################################################################
diff --git a/plugins/experimental/memcache/tsmemcache.cc b/plugins/experimental/memcache/tsmemcache.cc
index 1214934..8e405d3 100644
--- a/plugins/experimental/memcache/tsmemcache.cc
+++ b/plugins/experimental/memcache/tsmemcache.cc
@@ -145,7 +145,7 @@ MC::new_connection(NetVConnection *netvc, EThread *thread)
   rbuf             = new_MIOBuffer(MAX_IOBUFFER_SIZE);
   rbuf->water_mark = TSMEMCACHE_TMP_CMD_BUFFER_SIZE;
   reader           = rbuf->alloc_reader();
-  wbuf             = new_empty_MIOBuffer();
+  wbuf             = new_empty_MIOBuffer(BUFFER_SIZE_INDEX_32K);
   cbuf             = 0;
   writer           = wbuf->alloc_reader();
   SCOPED_MUTEX_LOCK(lock, mutex, thread);
@@ -826,7 +826,7 @@ MC::ascii_set_event(int event, void *data)
     if (f.set_append) {
       TS_PUSH_HANDLER(&MC::tunnel_event);
       if (!cbuf) {
-        cbuf = new_empty_MIOBuffer();
+        cbuf = new_empty_MIOBuffer(BUFFER_SIZE_INDEX_32K);
       }
       creader = cbuf->alloc_reader();
       crvio   = crvc->do_io_read(this, rcache_header->nbytes, cbuf);
@@ -838,7 +838,7 @@ MC::ascii_set_event(int event, void *data)
           a = static_cast<int64_t>(nbytes);
         }
         if (!cbuf) {
-          cbuf = new_empty_MIOBuffer();
+          cbuf = new_empty_MIOBuffer(BUFFER_SIZE_INDEX_32K);
         }
         creader = cbuf->alloc_reader();
         if (a) {
diff --git a/proxy/Transform.cc b/proxy/Transform.cc
index 9024f11..dd8e476 100644
--- a/proxy/Transform.cc
+++ b/proxy/Transform.cc
@@ -549,7 +549,7 @@ TransformControl::handle_event(int event, void * /* edata ATS_UNUSED */)
     }
     ink_assert(m_tvc != nullptr);
 
-    m_write_buf = new_MIOBuffer();
+    m_write_buf = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
     s           = m_write_buf->end();
     e           = m_write_buf->buf_end();
 
@@ -561,7 +561,7 @@ TransformControl::handle_event(int event, void * /* edata ATS_UNUSED */)
   }
 
   case TRANSFORM_READ_READY: {
-    MIOBuffer *buf = new_empty_MIOBuffer();
+    MIOBuffer *buf = new_empty_MIOBuffer(BUFFER_SIZE_INDEX_32K);
 
     m_read_buf = buf->alloc_reader();
     m_tvc->do_io_read(this, INT64_MAX, buf);
@@ -652,7 +652,7 @@ NullTransform::handle_event(int event, void *edata)
       ink_assert(m_output_vc != nullptr);
 
       if (!m_output_vio) {
-        m_output_buf    = new_empty_MIOBuffer();
+        m_output_buf    = new_empty_MIOBuffer(BUFFER_SIZE_INDEX_32K);
         m_output_reader = m_output_buf->alloc_reader();
         m_output_vio    = m_output_vc->do_io_write(this, m_write_vio.nbytes, m_output_reader);
       }
@@ -802,7 +802,7 @@ RangeTransform::handle_event(int event, void *edata)
       ink_assert(m_output_vc != nullptr);
 
       if (!m_output_vio) {
-        m_output_buf    = new_empty_MIOBuffer();
+        m_output_buf    = new_empty_MIOBuffer(BUFFER_SIZE_INDEX_32K);
         m_output_reader = m_output_buf->alloc_reader();
         m_output_vio    = m_output_vc->do_io_write(this, m_output_cl, m_output_reader);
 
diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc
index a7e83ff..b32e39c 100644
--- a/proxy/http/HttpConfig.cc
+++ b/proxy/http/HttpConfig.cc
@@ -1329,6 +1329,8 @@ HttpConfig::startup()
   HttpEstablishStaticConfigByte(c.enable_http_info, "proxy.config.http.enable_http_info");
 
   HttpEstablishStaticConfigLongLong(c.max_post_size, "proxy.config.http.max_post_size");
+  HttpEstablishStaticConfigLongLong(c.max_payload_iobuf_index, "proxy.config.payload.io.max_buffer_index");
+  HttpEstablishStaticConfigLongLong(c.max_msg_iobuf_index, "proxy.config.msg.io.max_buffer_index");
 
   //##############################################################################
   //#
@@ -1573,6 +1575,8 @@ HttpConfig::reconfigure()
 
   params->oride.cache_when_to_revalidate = m_master.oride.cache_when_to_revalidate;
   params->max_post_size                  = m_master.max_post_size;
+  params->max_payload_iobuf_index        = m_master.max_payload_iobuf_index;
+  params->max_msg_iobuf_index            = m_master.max_msg_iobuf_index;
 
   params->oride.cache_required_headers = m_master.oride.cache_required_headers;
   params->oride.cache_range_lookup     = INT_TO_BOOL(m_master.oride.cache_range_lookup);
diff --git a/proxy/http/HttpConfig.h b/proxy/http/HttpConfig.h
index 659e8e9..f4f146b 100644
--- a/proxy/http/HttpConfig.h
+++ b/proxy/http/HttpConfig.h
@@ -770,6 +770,9 @@ public:
   MgmtInt post_copy_size = 2048;
   MgmtInt max_post_size  = 0;
 
+  MgmtInt max_payload_iobuf_index = BUFFER_SIZE_INDEX_32K;
+  MgmtInt max_msg_iobuf_index     = BUFFER_SIZE_INDEX_32K;
+
   char *redirect_actions_string                        = nullptr;
   IpMap *redirect_actions_map                          = nullptr;
   RedirectEnabled::Action redirect_actions_self_action = RedirectEnabled::Action::INVALID;
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 1c20f87..c6a37e5 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -800,7 +800,7 @@ HttpSM::state_read_client_request_header(int event, void *data)
       // When receive an "Expect: 100-continue" request from client, ATS sends a "100 Continue" response to client
       // immediately, before receive the real response from original server.
       if ((len == HTTP_LEN_100_CONTINUE) && (strncasecmp(expect, HTTP_VALUE_100_CONTINUE, HTTP_LEN_100_CONTINUE) == 0)) {
-        int64_t alloc_index = buffer_size_to_index(len_100_continue_response);
+        int64_t alloc_index = buffer_size_to_index(len_100_continue_response, t_state.http_config_param->max_payload_iobuf_index);
         if (ua_entry->write_buffer) {
           free_MIOBuffer(ua_entry->write_buffer);
           ua_entry->write_buffer = nullptr;
@@ -855,7 +855,7 @@ HttpSM::wait_for_full_body()
       alloc_index = DEFAULT_REQUEST_BUFFER_SIZE_INDEX;
     }
   } else {
-    alloc_index = buffer_size_to_index(t_state.hdr_info.request_content_length);
+    alloc_index = buffer_size_to_index(t_state.hdr_info.request_content_length, t_state.http_config_param->max_payload_iobuf_index);
   }
   MIOBuffer *post_buffer    = new_MIOBuffer(alloc_index);
   IOBufferReader *buf_start = post_buffer->alloc_reader();
@@ -5682,7 +5682,7 @@ HttpSM::setup_transform_to_server_transfer()
   ink_assert(post_transform_info.entry->vc == post_transform_info.vc);
 
   int64_t nbytes            = t_state.hdr_info.transform_request_cl;
-  int64_t alloc_index       = buffer_size_to_index(nbytes);
+  int64_t alloc_index       = buffer_size_to_index(nbytes, t_state.http_config_param->max_payload_iobuf_index);
   MIOBuffer *post_buffer    = new_MIOBuffer(alloc_index);
   IOBufferReader *buf_start = post_buffer->alloc_reader();
 
@@ -5745,7 +5745,7 @@ HttpSM::do_setup_post_tunnel(HttpVC_t to_vc_type)
       (t_state.redirect_info.redirect_in_process && enable_redirection && this->_postbuf.postdata_copy_buffer_start != nullptr)) {
     post_redirect = true;
     // copy the post data into a new producer buffer for static producer
-    MIOBuffer *postdata_producer_buffer      = new_empty_MIOBuffer();
+    MIOBuffer *postdata_producer_buffer      = new_empty_MIOBuffer(t_state.http_config_param->max_payload_iobuf_index);
     IOBufferReader *postdata_producer_reader = postdata_producer_buffer->alloc_reader();
 
     postdata_producer_buffer->write(this->_postbuf.postdata_copy_buffer_start);
@@ -5762,7 +5762,8 @@ HttpSM::do_setup_post_tunnel(HttpVC_t to_vc_type)
         alloc_index = DEFAULT_REQUEST_BUFFER_SIZE_INDEX;
       }
     } else {
-      alloc_index = buffer_size_to_index(t_state.hdr_info.request_content_length);
+      alloc_index =
+        buffer_size_to_index(t_state.hdr_info.request_content_length, t_state.http_config_param->max_payload_iobuf_index);
     }
     MIOBuffer *post_buffer    = new_MIOBuffer(alloc_index);
     IOBufferReader *buf_start = post_buffer->alloc_reader();
@@ -6202,7 +6203,8 @@ HttpSM::setup_cache_read_transfer()
   ink_assert(cache_sm.cache_read_vc != nullptr);
 
   doc_size    = t_state.cache_info.object_read->object_size_get();
-  alloc_index = buffer_size_to_index(doc_size + index_to_buffer_size(HTTP_HEADER_BUFFER_SIZE_INDEX));
+  alloc_index = buffer_size_to_index(doc_size + index_to_buffer_size(HTTP_HEADER_BUFFER_SIZE_INDEX),
+                                     t_state.http_config_param->max_payload_iobuf_index);
 
 #ifndef USE_NEW_EMPTY_MIOBUFFER
   MIOBuffer *buf = new_MIOBuffer(alloc_index);
@@ -6255,7 +6257,7 @@ HttpSM::setup_cache_transfer_to_transform()
   cache_response_hdr_bytes = t_state.hdr_info.cache_response.length_get();
 
   doc_size                  = t_state.cache_info.object_read->object_size_get();
-  alloc_index               = buffer_size_to_index(doc_size);
+  alloc_index               = buffer_size_to_index(doc_size, t_state.http_config_param->max_payload_iobuf_index);
   MIOBuffer *buf            = new_MIOBuffer(alloc_index);
   IOBufferReader *buf_start = buf->alloc_reader();
 
@@ -6400,7 +6402,7 @@ HttpSM::setup_internal_transfer(HttpSMHandler handler_arg)
   int64_t buf_size =
     index_to_buffer_size(HTTP_HEADER_BUFFER_SIZE_INDEX) + (is_msg_buf_present ? t_state.internal_msg_buffer_size : 0);
 
-  MIOBuffer *buf            = new_MIOBuffer(buffer_size_to_index(buf_size));
+  MIOBuffer *buf            = new_MIOBuffer(buffer_size_to_index(buf_size, t_state.http_config_param->max_payload_iobuf_index));
   IOBufferReader *buf_start = buf->alloc_reader();
 
   // First write the client response header into the buffer
@@ -6468,7 +6470,7 @@ HttpSM::find_http_resp_buffer_size(int64_t content_length)
     }
   } else {
     int64_t buf_size = index_to_buffer_size(HTTP_HEADER_BUFFER_SIZE_INDEX) + content_length;
-    alloc_index      = buffer_size_to_index(buf_size);
+    alloc_index      = buffer_size_to_index(buf_size, t_state.http_config_param->max_payload_iobuf_index);
   }
 
   return alloc_index;
diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index 241d90e..b2f8859 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -5572,8 +5572,9 @@ HttpTransact::handle_trace_and_options_requests(State *s, HTTPHdr *incoming_hdr)
       s->free_internal_msg_buffer();
       s->internal_msg_buffer_size = req_length * 2;
 
-      if (s->internal_msg_buffer_size <= max_iobuffer_size) {
-        s->internal_msg_buffer_fast_allocator_size = buffer_size_to_index(s->internal_msg_buffer_size);
+      if (s->internal_msg_buffer_size <= BUFFER_SIZE_FOR_INDEX(s->http_config_param->max_msg_iobuf_index)) {
+        s->internal_msg_buffer_fast_allocator_size =
+          buffer_size_to_index(s->internal_msg_buffer_size, s->http_config_param->max_msg_iobuf_index);
         s->internal_msg_buffer = static_cast<char *>(ioBufAllocator[s->internal_msg_buffer_fast_allocator_size].alloc_void());
       } else {
         s->internal_msg_buffer_fast_allocator_size = -1;
diff --git a/proxy/http2/unit_tests/test_Http2Frame.cc b/proxy/http2/unit_tests/test_Http2Frame.cc
index d1e695e..8bd05c1 100644
--- a/proxy/http2/unit_tests/test_Http2Frame.cc
+++ b/proxy/http2/unit_tests/test_Http2Frame.cc
@@ -27,7 +27,7 @@
 
 TEST_CASE("Http2Frame", "[http2][Http2Frame]")
 {
-  MIOBuffer *miob        = new_MIOBuffer();
+  MIOBuffer *miob        = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
   IOBufferReader *miob_r = miob->alloc_reader();
 
   SECTION("PUSH_PROMISE")
diff --git a/proxy/http3/Http3HeaderFramer.cc b/proxy/http3/Http3HeaderFramer.cc
index 0931acc..316b028 100644
--- a/proxy/http3/Http3HeaderFramer.cc
+++ b/proxy/http3/Http3HeaderFramer.cc
@@ -97,7 +97,7 @@ Http3HeaderFramer::_generate_header_block()
     HTTPHdr h3_hdr;
     this->_convert_header_from_1_1_to_3(&h3_hdr, &this->_header);
 
-    this->_header_block        = new_MIOBuffer();
+    this->_header_block        = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
     this->_header_block_reader = this->_header_block->alloc_reader();
 
     this->_qpack->encode(this->_stream_id, h3_hdr, this->_header_block, this->_header_block_len);
diff --git a/proxy/http3/test/test_QPACK.cc b/proxy/http3/test/test_QPACK.cc
index f76626d..180554f 100644
--- a/proxy/http3/test/test_QPACK.cc
+++ b/proxy/http3/test/test_QPACK.cc
@@ -301,7 +301,7 @@ test_encode(const char *qif_file, const char *out_file, int dts, int mbs, int am
   qpack->set_stream(decoder_stream);
 
   uint64_t stream_id                  = 1;
-  MIOBuffer *header_block             = new_MIOBuffer();
+  MIOBuffer *header_block             = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
   uint64_t header_block_len           = 0;
   IOBufferReader *header_block_reader = header_block->alloc_reader();
   for (int i = 0; i < n_requests; ++i) {
diff --git a/proxy/logging/LogBuffer.cc b/proxy/logging/LogBuffer.cc
index 90472fc..5dc19f4 100644
--- a/proxy/logging/LogBuffer.cc
+++ b/proxy/logging/LogBuffer.cc
@@ -111,8 +111,8 @@ LogBuffer::LogBuffer(LogObject *owner, size_t size, size_t buf_align, size_t wri
   //
   int64_t alloc_size = size + buf_align;
 
-  if (alloc_size <= max_iobuffer_size) {
-    m_buffer_fast_allocator_size = buffer_size_to_index(alloc_size);
+  if (alloc_size <= BUFFER_SIZE_FOR_INDEX(Log::config->logbuffer_max_iobuf_index)) {
+    m_buffer_fast_allocator_size = buffer_size_to_index(alloc_size, Log::config->logbuffer_max_iobuf_index);
     m_unaligned_buffer           = static_cast<char *>(ioBufAllocator[m_buffer_fast_allocator_size].alloc_void());
   } else {
     m_buffer_fast_allocator_size = -1;
diff --git a/proxy/logging/LogConfig.cc b/proxy/logging/LogConfig.cc
index 9a8c602..d35eed14 100644
--- a/proxy/logging/LogConfig.cc
+++ b/proxy/logging/LogConfig.cc
@@ -96,8 +96,9 @@ LogConfig::setup_default_values()
   file_stat_frequency  = 16;
   space_used_frequency = 900;
 
-  ascii_buffer_size = 4 * 9216;
-  max_line_size     = 9216; // size of pipe buffer for SunOS 5.6
+  ascii_buffer_size         = 4 * 9216;
+  max_line_size             = 9216; // size of pipe buffer for SunOS 5.6
+  logbuffer_max_iobuf_index = BUFFER_SIZE_INDEX_32K;
 }
 
 void LogConfig::reconfigure_mgmt_variables(ts::MemSpan<void>)
@@ -145,6 +146,11 @@ LogConfig::read_configuration_variables()
     max_space_mb_headroom = val;
   }
 
+  val = static_cast<int>(REC_ConfigReadInteger("proxy.config.log.io.max_buffer_index"));
+  if (val > 0) {
+    logbuffer_max_iobuf_index = val;
+  }
+
   ptr                     = REC_ConfigReadString("proxy.config.log.logfile_perm");
   int logfile_perm_parsed = ink_fileperm_parse(ptr);
   if (logfile_perm_parsed != -1) {
@@ -359,6 +365,7 @@ LogConfig::display(FILE *fd)
   fprintf(fd, "   sampling_frequency = %d\n", sampling_frequency);
   fprintf(fd, "   file_stat_frequency = %d\n", file_stat_frequency);
   fprintf(fd, "   space_used_frequency = %d\n", space_used_frequency);
+  fprintf(fd, "   logbuffer_max_iobuf_index = %d\n", logbuffer_max_iobuf_index);
 
   fprintf(fd, "\n");
   fprintf(fd, "************ Log Objects (%u objects) ************\n", log_object_manager.get_num_objects());
@@ -434,6 +441,7 @@ LogConfig::register_config_callbacks()
     "proxy.config.log.rolling_offset_hr",     "proxy.config.log.rolling_size_mb",     "proxy.config.log.auto_delete_rolled_files",
     "proxy.config.log.rolling_max_count",     "proxy.config.log.rolling_allow_empty", "proxy.config.log.config.filename",
     "proxy.config.log.sampling_frequency",    "proxy.config.log.file_stat_frequency", "proxy.config.log.space_used_frequency",
+    "proxy.config.log.io.max_buffer_index",
   };
 
   for (unsigned i = 0; i < countof(names); ++i) {
diff --git a/proxy/logging/LogConfig.h b/proxy/logging/LogConfig.h
index 0f5eac7..858d64e 100644
--- a/proxy/logging/LogConfig.h
+++ b/proxy/logging/LogConfig.h
@@ -205,6 +205,7 @@ public:
 
   int ascii_buffer_size;
   int max_line_size;
+  int logbuffer_max_iobuf_index;
 
   char *hostname;
   char *logfile_dir;
diff --git a/src/traffic_quic/quic_client.cc b/src/traffic_quic/quic_client.cc
index 7f3ec64..c6d15b7 100644
--- a/src/traffic_quic/quic_client.cc
+++ b/src/traffic_quic/quic_client.cc
@@ -268,8 +268,8 @@ Http3ClientApp::~Http3ClientApp()
 void
 Http3ClientApp::start()
 {
-  this->_req_buf                  = new_MIOBuffer();
-  this->_resp_buf                 = new_MIOBuffer();
+  this->_req_buf                  = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
+  this->_resp_buf                 = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
   IOBufferReader *resp_buf_reader = _resp_buf->alloc_reader();
 
   this->_resp_handler = new RespHandler(this->_config, resp_buf_reader);
diff --git a/src/traffic_server/InkAPITest.cc b/src/traffic_server/InkAPITest.cc
index e1273c2..1b0bad1 100644
--- a/src/traffic_server/InkAPITest.cc
+++ b/src/traffic_server/InkAPITest.cc
@@ -2946,7 +2946,7 @@ REGRESSION_TEST(SDK_API_TSIOBufferBlockReadAvail)(RegressionTest *test, int /* a
     SDK_RPRINT(test, "TSIOBufferBlockWriteStart", "TestCase1", TC_FAIL, "failed");
   }
 
-  if ((TSIOBufferBlockReadAvail(blockp, readerp) + TSIOBufferBlockWriteAvail(blockp)) == 4096) {
+  if ((TSIOBufferBlockReadAvail(blockp, readerp) + TSIOBufferBlockWriteAvail(blockp)) == 32768) {
     SDK_RPRINT(test, "TSIOBufferBlockReadAvail", "TestCase1", TC_PASS, "ok");
     SDK_RPRINT(test, "TSIOBufferBlockWriteAvail", "TestCase1", TC_PASS, "ok");
     test_passed_2 = true;
diff --git a/src/traffic_server/InkIOCoreAPI.cc b/src/traffic_server/InkIOCoreAPI.cc
index 1740ee1..5a52101 100644
--- a/src/traffic_server/InkIOCoreAPI.cc
+++ b/src/traffic_server/InkIOCoreAPI.cc
@@ -567,7 +567,7 @@ INKUDPPacketGet(INKUDPacketQueue queuep)
 TSIOBuffer
 TSIOBufferCreate()
 {
-  MIOBuffer *b = new_empty_MIOBuffer();
+  MIOBuffer *b = new_empty_MIOBuffer(BUFFER_SIZE_INDEX_32K);
 
   // TODO: Should remove this when memory allocations can't fail.
   sdk_assert(sdk_sanity_check_iocore_structure(b) == TS_SUCCESS);
diff --git a/src/traffic_server/SocksProxy.cc b/src/traffic_server/SocksProxy.cc
index 06e88f8..c1f44c2 100644
--- a/src/traffic_server/SocksProxy.cc
+++ b/src/traffic_server/SocksProxy.cc
@@ -144,7 +144,7 @@ void
 SocksProxy::init(NetVConnection *netVC)
 {
   mutex  = new_ProxyMutex();
-  buf    = new_MIOBuffer();
+  buf    = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
   reader = buf->alloc_reader();
 
   SCOPED_MUTEX_LOCK(lock, mutex, this_ethread());