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

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 182dcdb  Add byte buffer reuse to IOUtils.
182dcdb is described below

commit 182dcdbc0799797c9a66697b4708832e18c80730
Author: JamesBognar <[email protected]>
AuthorDate: Mon Mar 8 13:53:29 2021 -0500

    Add byte buffer reuse to IOUtils.
---
 .../apache/juneau/internal/FileWriterBuilder.java  | 17 ++++-
 .../java/org/apache/juneau/internal/IOUtils.java   | 88 ++++++++++++----------
 2 files changed, 64 insertions(+), 41 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/FileWriterBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/FileWriterBuilder.java
index 1e63f8f..0c3e5af 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/FileWriterBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/FileWriterBuilder.java
@@ -22,7 +22,7 @@ public final class FileWriterBuilder {
 
        private File file;
        private Charset cs = Charset.defaultCharset();
-       private boolean append;
+       private boolean append, buffered;
 
        /**
         * Creates a new builder.
@@ -112,12 +112,25 @@ public final class FileWriterBuilder {
        }
 
        /**
+        * Sets the buffer mode on the writer to <jk>true</jk>.
+        *
+        * @return This object (for method chaining).
+        */
+       public FileWriterBuilder buffered() {
+               this.buffered = true;
+               return this;
+       }
+
+       /**
         * Creates a new File writer.
         *
         * @return A new File writer.
         * @throws FileNotFoundException If file could not be found.
         */
        public Writer build() throws FileNotFoundException {
-               return new OutputStreamWriter(new FileOutputStream(file, 
append), cs);
+               OutputStream os = new FileOutputStream(file, append);
+               if (buffered)
+                       os = new BufferedOutputStream(os);
+               return new OutputStreamWriter(os, cs);
        }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/IOUtils.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/IOUtils.java
index 11760d0..c95ac5f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/IOUtils.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/IOUtils.java
@@ -15,6 +15,7 @@ package org.apache.juneau.internal;
 import java.io.*;
 import java.nio.charset.*;
 import java.util.*;
+import java.util.concurrent.atomic.*;
 
 /**
  * Various I/O related utility methods.
@@ -32,6 +33,20 @@ public final class IOUtils {
                }
        };
 
+       private static final ThreadLocal<byte[]> BYTE_BUFFER_CACHE = 
(Boolean.getBoolean("juneau.disableIoBufferReuse") ? null : new 
ThreadLocal<>());
+       private static final ThreadLocal<char[]> CHAR_BUFFER_CACHE = 
(Boolean.getBoolean("juneau.disableIoBufferReuse") ? null : new 
ThreadLocal<>());
+
+       static final AtomicInteger cacheHits = new AtomicInteger();
+
+       static {
+               Runtime.getRuntime().addShutdownHook(new Thread() {
+                       @Override
+                       public void run() {
+                               System.out.println("I/O buffer cache hits: " + 
cacheHits.get());
+                       }
+               });
+       }
+
        /** Reusable empty reader. */
        public static final Reader EMPTY_READER = new Reader() {
                @Override
@@ -69,7 +84,7 @@ public final class IOUtils {
        public static long pipe(Reader in, File out) throws IOException {
                if (out == null || in == null)
                        return 0;
-               try (Writer w = FileWriterBuilder.create(out).build()) {
+               try (Writer w = 
FileWriterBuilder.create(out).buffered().build()) {
                        return pipe(in, w);
                }
        }
@@ -94,7 +109,7 @@ public final class IOUtils {
                        return 0;
                long total = 0;
                try (Reader in2 = in) {
-                       char[] buffer = new char[buffSize(-1)];
+                       char[] buffer = charBuffer(-1);
                        int readLen;
                        while ((readLen = in.read(buffer)) != -1) {
                                out.write(buffer, 0, readLen);
@@ -209,7 +224,7 @@ public final class IOUtils {
        public static long pipe(InputStream in, OutputStream out, long 
maxBytes) throws IOException {
                if (in == null || out == null)
                        return 0;
-               byte[] buffer = new byte[buffSize(maxBytes)];
+               byte[] buffer = byteBuffer((int)maxBytes);
                int readLen;
                long total = 0;
                if (maxBytes < 0) {
@@ -253,7 +268,7 @@ public final class IOUtils {
                try (Reader in2 = in) {
                        OutputStreamWriter osw = new OutputStreamWriter(out, 
UTF8);
                        int i;
-                       char[] b = new char[BUFF_SIZE];
+                       char[] b = charBuffer(-1);
                        while ((i = in.read(b)) > 0) {
                                total += i;
                                osw.write(b, 0, i);
@@ -373,7 +388,7 @@ public final class IOUtils {
                        return null;
                try (Reader in2 = in) {
                        StringBuilder sb = new 
StringBuilder(buffSize(expectedLength)); // Assume they're ASCII characters.
-                       char[] buf = new char[buffSize(expectedLength)];
+                       char[] buf = charBuffer((int)expectedLength);
                        int i = 0;
                        while ((i = in2.read(buf)) != -1)
                                sb.append(buf, 0, i);
@@ -421,39 +436,6 @@ public final class IOUtils {
        }
 
        /**
-        * Shortcut for calling <c>readBytes(in, 1024);</c>
-        *
-        * @param in
-        *      The object to read into a byte array.
-        *      <br>Can be any of the following types:
-        *      <ul>
-        *              <li><code><jk>byte</jk>[]</code>
-        *              <li>{@link InputStream}
-        *              <li>{@link Reader}
-        *              <li>{@link CharSequence}
-        *              <li>{@link File}
-        *      </ul>
-        * @return The contents of the stream as a byte array.
-        * @throws IOException Thrown by underlying stream or if object is not 
a supported type.
-        */
-       @Deprecated
-       public static byte[] readBytes(Object in) throws IOException {
-               if (in == null)
-                       return new byte[0];
-               if (in instanceof byte[])
-                       return (byte[])in;
-               if (in instanceof CharSequence)
-                       return in.toString().getBytes(UTF8);
-               if (in instanceof InputStream)
-                       return readBytes((InputStream)in);
-               if (in instanceof Reader)
-                       return read((Reader)in, 0).getBytes(UTF8);
-               if (in instanceof File)
-                       return readBytes((File)in);
-               throw new IOException("Cannot convert object of type 
'"+in.getClass().getName()+"' to a byte array.");
-       }
-
-       /**
         * Reads the specified input stream into the specified byte array.
         *
         * @param in
@@ -486,7 +468,7 @@ public final class IOUtils {
                        return new byte[0];
                ByteArrayOutputStream buff = new 
ByteArrayOutputStream(buffSize(maxBytes));
                int nRead;
-               byte[] b = new byte[buffSize(maxBytes)];
+               byte[] b = byteBuffer(maxBytes);
                while ((nRead = in.read(b, 0, b.length)) != -1)
                        buff.write(b, 0, nRead);
                buff.flush();
@@ -765,6 +747,34 @@ public final class IOUtils {
                return null;
        }
 
+       private static final byte[] byteBuffer(int maxBytes) {
+               if (BYTE_BUFFER_CACHE != null) {
+                       byte[] x = BYTE_BUFFER_CACHE.get();
+                       if (x == null) {
+                                x = new byte[BUFF_SIZE];
+                                BYTE_BUFFER_CACHE.set(x);
+                       } else {
+                               cacheHits.incrementAndGet();
+                       }
+                       return x;
+               }
+               return new byte[buffSize(maxBytes)];
+       }
+
+       private static final char[] charBuffer(int maxChars) {
+               if (CHAR_BUFFER_CACHE != null) {
+                       char[] x = CHAR_BUFFER_CACHE.get();
+                       if (x == null) {
+                                x = new char[BUFF_SIZE];
+                                CHAR_BUFFER_CACHE.set(x);
+                       } else {
+                               cacheHits.incrementAndGet();
+                       }
+                       return x;
+               }
+               return new char[buffSize(maxChars)];
+       }
+
        private static final int buffSize(long max) {
                return (max > 0 && max < BUFF_SIZE) ? (int)max : BUFF_SIZE;
        }

Reply via email to