From 34b5a5fba08c1cdb35af7879fa4c06f51dc122e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Fri, 30 Sep 2022 19:48:24 +0200 Subject: [PATCH] AFCore: Revert limit to 1MB; allocate buffers on-the-fly if exceeded The limit to how large datagram can be seems to have no feasibly low limit (25MB datagrams have been reported to work). This imposes a challenge on caching/reuse strategies for direct byte buffers (a shared, reusable pool that is not thread-specific could be an alternative, but comes at the cost of complexity). At the cost of performance, revert the per-thread limit to 1MB, and return newly allocated direct byte buffers instead of cached ones whenever the limit is exceeded. Users of such unexpectedly large datagrams could either still force a higher (or unbounded) limit via the system property "org.newsclub.net.unix.thread-local-buffer.max-capacity", or better, use direct byte buffers in the calling code, obsoleting the need to use this cache in the first place. https://github.com/kohlschutter/junixsocket/issues/118 --- .../java/org/newsclub/net/unix/AFCore.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFCore.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFCore.java index 8b2ab460d..0b67705ad 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFCore.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFCore.java @@ -37,8 +37,7 @@ class AFCore extends CleanableState { private static final int TL_BUFFER_MIN_CAPACITY = 8192; // 8 kb per thread private static final int TL_BUFFER_MAX_CAPACITY = Integer.parseInt(System.getProperty( - PROP_TL_BUFFER_MAX_CAPACITY, Integer.toString(8 * 1024 * 1024))); // 8 MB per thread, - // realistic upper limit + PROP_TL_BUFFER_MAX_CAPACITY, Integer.toString(1 * 1024 * 1024))); // 1 MB per thread private final AtomicBoolean closed = new AtomicBoolean(false); @@ -209,9 +208,22 @@ int write(ByteBuffer src, SocketAddress target, int options) throws IOException return written; } + /** + * Returns a per-thread reusable byte buffer for a given capacity. + * + * If a thread-local buffer currently uses a smaller capacity, the buffer is replaced by a larger + * one. If the capacity exceeds a configurable maximum, a new direct buffer is allocated but not + * cached (i.e., the previously cached one is kept but not immediately returned to the caller). + * + * @param capacity The desired capacity. + * @return A byte buffer satisfying the requested capacity. + */ ByteBuffer getThreadLocalDirectByteBuffer(int capacity) { if (capacity > TL_BUFFER_MAX_CAPACITY && TL_BUFFER_MAX_CAPACITY > 0) { - capacity = TL_BUFFER_MAX_CAPACITY; + // Capacity exceeds configurable maximum limit; + // allocate but do not cache direct buffer. + // This may incur a performance penalty at the cost of correctness when using such capacities. + return ByteBuffer.allocateDirect(capacity); } if (capacity < TL_BUFFER_MIN_CAPACITY) { capacity = TL_BUFFER_MIN_CAPACITY;