Make ZKPaths.makePath() methods to allocate less garbage
authorRoman Leventov <leventov.ru@gmail.com>
Mon, 10 Dec 2018 18:37:52 +0000 (19:37 +0100)
committerRoman Leventov <leventov.ru@gmail.com>
Mon, 10 Dec 2018 18:37:52 +0000 (19:37 +0100)
curator-client/src/main/java/org/apache/curator/utils/ZKPaths.java
curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/DistributedDelayQueue.java

index 8e94d2b..378e25d 100644 (file)
@@ -38,6 +38,8 @@ public class ZKPaths
      */
     public static final String PATH_SEPARATOR = "/";
 
+    private static final char PATH_SEPARATOR_CHAR = '/';
+
     private static final CreateMode NON_CONTAINER_MODE = CreateMode.PERSISTENT;
 
     /**
@@ -120,7 +122,7 @@ public class ZKPaths
     public static String getNodeFromPath(String path)
     {
         PathUtils.validatePath(path);
-        int i = path.lastIndexOf(PATH_SEPARATOR);
+        int i = path.lastIndexOf(PATH_SEPARATOR_CHAR);
         if ( i < 0 )
         {
             return path;
@@ -163,7 +165,7 @@ public class ZKPaths
     public static PathAndNode getPathAndNode(String path)
     {
         PathUtils.validatePath(path);
-        int i = path.lastIndexOf(PATH_SEPARATOR);
+        int i = path.lastIndexOf(PATH_SEPARATOR_CHAR);
         if ( i < 0 )
         {
             return new PathAndNode(path, "");
@@ -192,7 +194,7 @@ public class ZKPaths
         return length > SEQUENTIAL_SUFFIX_DIGITS ? path.substring(length - SEQUENTIAL_SUFFIX_DIGITS) : path;
     }
 
-    private static final Splitter PATH_SPLITTER = Splitter.on(PATH_SEPARATOR).omitEmptyStrings();
+    private static final Splitter PATH_SPLITTER = Splitter.on(PATH_SEPARATOR_CHAR).omitEmptyStrings();
 
     /**
      * Given a full path, return the the individual parts, without slashes.
@@ -271,7 +273,7 @@ public class ZKPaths
         int pos = 1; // skip first slash, root is guaranteed to exist
         do
         {
-            pos = path.indexOf(PATH_SEPARATOR, pos + 1);
+            pos = path.indexOf(PATH_SEPARATOR_CHAR, pos + 1);
 
             if ( pos == -1 )
             {
@@ -388,7 +390,10 @@ public class ZKPaths
      */
     public static String makePath(String parent, String child)
     {
-        StringBuilder path = new StringBuilder();
+        // 2 is the maximum number of additional path separators inserted
+        int maxPathLength = nullableStringLength(parent) + nullableStringLength(child) + 2;
+        // Avoid internal StringBuilder's buffer reallocation by specifying the max path length
+        StringBuilder path = new StringBuilder(maxPathLength);
 
         joinPath(path, parent, child);
 
@@ -405,7 +410,18 @@ public class ZKPaths
      */
     public static String makePath(String parent, String firstChild, String... restChildren)
     {
-        StringBuilder path = new StringBuilder();
+        // 2 is the maximum number of additional path separators inserted
+        int maxPathLength = nullableStringLength(parent) + nullableStringLength(firstChild) + 2;
+        if ( restChildren != null )
+        {
+            for ( String child : restChildren )
+            {
+                // 1 is for possible additional separator
+                maxPathLength += nullableStringLength(child) + 1;
+            }
+        }
+        // Avoid internal StringBuilder's buffer reallocation by specifying the max path length
+        StringBuilder path = new StringBuilder(maxPathLength);
 
         joinPath(path, parent, firstChild);
 
@@ -424,6 +440,11 @@ public class ZKPaths
         }
     }
 
+    private static int nullableStringLength(String s)
+    {
+        return s != null ? s.length() : 0;
+    }
+
     /**
      * Given a parent and a child node, join them in the given {@link StringBuilder path}
      *
@@ -436,13 +457,13 @@ public class ZKPaths
         // Add parent piece, with no trailing slash.
         if ( (parent != null) && (parent.length() > 0) )
         {
-            if ( !parent.startsWith(PATH_SEPARATOR) )
+            if ( parent.charAt(0) != PATH_SEPARATOR_CHAR )
             {
-                path.append(PATH_SEPARATOR);
+                path.append(PATH_SEPARATOR_CHAR);
             }
-            if ( parent.endsWith(PATH_SEPARATOR) )
+            if ( parent.charAt(parent.length() - 1) == PATH_SEPARATOR_CHAR )
             {
-                path.append(parent.substring(0, parent.length() - 1));
+                path.append(parent, 0, parent.length() - 1);
             }
             else
             {
@@ -450,31 +471,42 @@ public class ZKPaths
             }
         }
 
-        if ( (child == null) || (child.length() == 0) || (child.equals(PATH_SEPARATOR)) )
+        if ( (child == null) || (child.length() == 0) ||
+                (child.length() == 1 && child.charAt(0) == PATH_SEPARATOR_CHAR) )
         {
             // Special case, empty parent and child
             if ( path.length() == 0 )
             {
-                path.append(PATH_SEPARATOR);
+                path.append(PATH_SEPARATOR_CHAR);
             }
             return;
         }
 
         // Now add the separator between parent and child.
-        path.append(PATH_SEPARATOR);
+        path.append(PATH_SEPARATOR_CHAR);
 
-        if ( child.startsWith(PATH_SEPARATOR) )
+        int childAppendBeginIndex;
+        if ( child.charAt(0) == PATH_SEPARATOR_CHAR )
+        {
+            childAppendBeginIndex = 1;
+        }
+        else
         {
-            child = child.substring(1);
+            childAppendBeginIndex = 0;
         }
 
-        if ( child.endsWith(PATH_SEPARATOR) )
+        int childAppendEndIndex;
+        if ( child.charAt(child.length() - 1) == PATH_SEPARATOR_CHAR )
+        {
+            childAppendEndIndex = child.length() - 1;
+        }
+        else
         {
-            child = child.substring(0, child.length() - 1);
+            childAppendEndIndex = child.length();
         }
 
         // Finally, add the child.
-        path.append(child);
+        path.append(child, childAppendBeginIndex, childAppendEndIndex);
     }
 
     private ZKPaths()
index ff39f42..8f321b3 100644 (file)
@@ -42,7 +42,7 @@ public class DistributedDelayQueue<T> implements Closeable, QueueBase<T>
 {
     private final DistributedQueue<T>      queue;
 
-    private static final String            SEPARATOR = "|";
+    private static final char              SEPARATOR = '|';
 
     DistributedDelayQueue
         (