Skip to content

Commit 498aaaa

Browse files
authored
Merge pull request #2722 from zspitzer/LDEV-5953
LDEV-5953 Use ThreadLocal buffer pools for IOUtil
2 parents e89ecac + e8062b7 commit 498aaaa

File tree

1 file changed

+24
-23
lines changed

1 file changed

+24
-23
lines changed

core/src/main/java/lucee/commons/io/IOUtil.java

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,7 @@
3737
import java.io.UnsupportedEncodingException;
3838
import java.io.Writer;
3939
import java.net.URL;
40-
import java.nio.ByteBuffer;
41-
import java.nio.channels.Channels;
4240
import java.nio.channels.FileChannel;
43-
import java.nio.channels.ReadableByteChannel;
44-
import java.nio.channels.WritableByteChannel;
4541
import java.nio.charset.Charset;
4642
import java.nio.file.Files;
4743
import java.nio.file.Path;
@@ -71,6 +67,10 @@ public final class IOUtil {
7167

7268
private static final int DEFAULT_BLOCK_SIZE = 0xffff;// 65535
7369

70+
// ThreadLocal buffer pools to avoid repeated allocations in hot paths
71+
private static final ThreadLocal<byte[]> BYTE_ARRAY_POOL = ThreadLocal.withInitial( () -> new byte[DEFAULT_BLOCK_SIZE] );
72+
private static final ThreadLocal<char[]> CHAR_BUFFER_POOL = ThreadLocal.withInitial( () -> new char[DEFAULT_BLOCK_SIZE] );
73+
7474
/**
7575
* copy an inputstream to an outputstream
7676
*
@@ -326,24 +326,18 @@ public static final void copy(InputStream in, OutputStream out, int offset, int
326326
* @throws IOException If an I/O error occurs during the copy operation.
327327
*/
328328
private static final void copy(InputStream in, OutputStream out, int blockSize) throws IOException {
329-
// Creating channels from the input and output streams
330-
ReadableByteChannel sourceChannel = Channels.newChannel(in);
331-
WritableByteChannel destChannel = Channels.newChannel(out);
332-
333-
// Allocate a ByteBuffer of the given block size
334-
ByteBuffer buffer = ByteBuffer.allocate(blockSize);
335-
336-
// Read from the source channel into the buffer, and then write from the buffer to the destination
337-
// channel
338-
while (sourceChannel.read(buffer) != -1) {
339-
// Flip the buffer to prepare for writing
340-
buffer.flip();
341-
342-
// Write to the destination channel
343-
destChannel.write(buffer);
329+
// Use pooled buffer for default block size, otherwise allocate
330+
byte[] buffer;
331+
if ( blockSize == DEFAULT_BLOCK_SIZE ) {
332+
buffer = BYTE_ARRAY_POOL.get();
333+
}
334+
else {
335+
buffer = new byte[blockSize];
336+
}
344337

345-
// Clear the buffer for the next read
346-
buffer.clear();
338+
int len;
339+
while ( ( len = in.read( buffer ) ) != -1 ) {
340+
out.write( buffer, 0, len );
347341
}
348342
}
349343

@@ -356,7 +350,7 @@ private static final void copy(InputStream in, OutputStream out, int blockSize)
356350
* @throws IOException
357351
*/
358352
public static final boolean copyMax(InputStream in, OutputStream out, long max) throws IOException {
359-
byte[] buffer = new byte[DEFAULT_BLOCK_SIZE];
353+
byte[] buffer = BYTE_ARRAY_POOL.get();
360354
int len;
361355
long total = 0;
362356
while ((len = in.read(buffer)) != -1) {
@@ -418,7 +412,14 @@ public static final void copy(Reader reader, Writer writer, boolean closeReader,
418412
*/
419413
private static final void copy(Reader r, Writer w, int blockSize, long timeout) throws IOException {
420414
if (timeout < 1) {
421-
char[] buffer = new char[blockSize];
415+
// Use pooled buffer for default block size, otherwise allocate
416+
char[] buffer;
417+
if ( blockSize == DEFAULT_BLOCK_SIZE ) {
418+
buffer = CHAR_BUFFER_POOL.get();
419+
}
420+
else {
421+
buffer = new char[blockSize];
422+
}
422423
int len;
423424

424425
while ((len = r.read(buffer)) != -1)

0 commit comments

Comments
 (0)