[GitHub] [commons-lang] YuyuZha0 commented on a change in pull request #443: Optimize string split methods: 1. Use ThreadLocal to make reuse of th…

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[GitHub] [commons-lang] YuyuZha0 commented on a change in pull request #443: Optimize string split methods: 1. Use ThreadLocal to make reuse of th…

GitBox
YuyuZha0 commented on a change in pull request #443: Optimize string split methods: 1. Use ThreadLocal to make reuse of th…
URL: https://github.com/apache/commons-lang/pull/443#discussion_r317380836
 
 

 ##########
 File path: src/main/java/org/apache/commons/lang3/StringUtils.java
 ##########
 @@ -7968,9 +7968,145 @@ public static String rotate(final String str, final int shift) {
             }
         }
         if (match || preserveAllTokens && lastMatch) {
-            list.add(str.substring(start, i));
+            buffer.add(str.substring(start, i));
+        }
+        return buffer.toArray();
+    }
+
+    private static final ThreadLocal<SplitBufferThreadLocalHelper> SPLIT_BUFFER_THREAD_LOCAL
+            = new ThreadLocal<SplitBufferThreadLocalHelper>() {
+        @Override
+        protected SplitBufferThreadLocalHelper initialValue() {
+            return new SplitBufferThreadLocalHelper();
+        }
+    };
+
+    // Private class act as a buffer while splitting.
+    // "SplitBufferThreadLocalHelper" is constructed as a thread local variable so it is
+    // thread safe. The "splitBuffer" field acts as a buffer to hold the temporary
+    // representation of string split segments. It is shared by all
+    // calls to splitByCharacterType() or splitByWholeSeparatorWorker()
+    // or splitWorker(String) or splitWorker(char) and its variants in that particular thread.
+    private static final class SplitBufferThreadLocalHelper {
+
+        private final SplitBuffer splitBuffer = new SplitBuffer();
+
+        SplitBuffer getBuffer(){
+            splitBuffer.reset();
+            return splitBuffer;
+        }
+    }
+
+    //buffer class
+    private static final class SplitBuffer {
+
+        /**
+         * Default initial capacity.
+         */
+        private static final int DEFAULT_CAPACITY = 10;
+
+        /**
+         * Shared empty array instance used for default sized empty instances. We
+         * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
+         * first element is added.
+         */
+        private static final String[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
+
+        /**
+         * The maximum size of array to allocate (unless necessary).
+         * Some VMs reserve some header words in an array.
+         * Attempts to allocate larger arrays may result in
+         * OutOfMemoryError: Requested array size exceeds VM limit
+         */
+        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
+        private String[] elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
+        private int size = 0;
+
+        private static int hugeCapacity(int minCapacity) {
+            if (minCapacity < 0) {// overflow
+                throw new OutOfMemoryError();
+            }
+            return (minCapacity > MAX_ARRAY_SIZE)
+                    ? Integer.MAX_VALUE
+                    : MAX_ARRAY_SIZE;
+        }
+
+        String get(int index) {
+            return elementData[index];
+        }
+
+        void add(String e) {
+            add(e, elementData, size);
+        }
+
+        /**
+         * This helper method split out from add(E) to keep method
+         * bytecode size under 35 (the -XX:MaxInlineSize default value),
+         * which helps when add(E) is called in a C1-compiled loop.
+         */
+        private void add(String e, Object[] elementData, int s) {
+            if (s == elementData.length) {
+                elementData = grow(size + 1);
+            }
+            elementData[s] = e;
+            size = s + 1;
+        }
+
+        /**
+         * Increases the capacity to ensure that it can hold at least the
+         * number of elements specified by the minimum capacity argument.
+         *
+         * @param minCapacity the desired minimum capacity
+         * @throws OutOfMemoryError if minCapacity is less than zero
+         */
+        private String[] grow(int minCapacity) {
+            String[] newElementData = new String[newCapacity(minCapacity)];
+            System.arraycopy(elementData, 0, newElementData, 0, elementData.length);
+            return elementData = newElementData;
+        }
+
+        /**
+         * Returns a capacity at least as large as the given minimum capacity.
+         * Returns the current capacity increased by 50% if that suffices.
+         * Will not return a capacity greater than MAX_ARRAY_SIZE unless
+         * the given minimum capacity is greater than MAX_ARRAY_SIZE.
+         *
+         * @param minCapacity the desired minimum capacity
+         * @throws OutOfMemoryError if minCapacity is less than zero
+         */
+        private int newCapacity(int minCapacity) {
+            // overflow-conscious code
+            int oldCapacity = elementData.length;
+            int newCapacity = oldCapacity + (oldCapacity >> 1);
+            if (newCapacity - minCapacity <= 0) {
+                if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
+                    return Math.max(DEFAULT_CAPACITY, minCapacity);
+                }
+                if (minCapacity < 0) { // overflow
+                    throw new OutOfMemoryError();
 
 Review comment:
   I will edit this later.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[hidden email]


With regards,
Apache Git Services