RFR: patch to reduce use of many temporary objects in java.util.UUID

Robert Stupp snazy at gmx.de
Thu Nov 7 00:19:19 UTC 2013


Hi,

the current implementation of java.util.UUID.fromName() and java.util.UUID.toString() unnecessarily produce a lot of temporary objects. Especially the fromName() method creates some instances of java.lang.Long and indirectly via "name.split()" many Strings, an ArrayList, etc. UUID.toString() creates at least 10 String objects plus the implicitly created char[] instances.

Here's a hg diff which reduces the temporary object count while still providing the same functionality.

-
Robert




diff --git a/src/share/classes/java/util/UUID.java b/src/share/classes/java/util/UUID.java
--- a/src/share/classes/java/util/UUID.java
+++ b/src/share/classes/java/util/UUID.java
@@ -189,23 +189,68 @@
      *
      */
     public static UUID fromString(String name) {
-        String[] components = name.split("-");
-        if (components.length != 5)
+        if (name.length() != 36)
             throw new IllegalArgumentException("Invalid UUID string: "+name);
-        for (int i=0; i<5; i++)
-            components[i] = "0x"+components[i];
 
-        long mostSigBits = Long.decode(components[0]).longValue();
-        mostSigBits <<= 16;
-        mostSigBits |= Long.decode(components[1]).longValue();
-        mostSigBits <<= 16;
-        mostSigBits |= Long.decode(components[2]).longValue();
+        long lo;
+        long hi;
+        lo = hi = 0;
 
-        long leastSigBits = Long.decode(components[3]).longValue();
-        leastSigBits <<= 48;
-        leastSigBits |= Long.decode(components[4]).longValue();
+        for (int i = 0, j = 0; i < 36; ++j) {
+            // Need to bypass hyphens:
 
-        return new UUID(mostSigBits, leastSigBits);
+            switch (i) {
+                case 8:
+                case 13:
+                case 18:
+                case 23:
+                    if (name.charAt(i) != '-')
+                        throw new IllegalArgumentException("Invalid UUID string: "+name);
+
+                    ++i;
+            } // switch
+
+            int curr;
+            char c = name.charAt(i);
+
+            if (c >= '0' && c <= '9')
+                curr = (c - '0');
+
+            else if (c >= 'a' && c <= 'f')
+                curr = (c - 'a' + 10);
+
+            else if (c >= 'A' && c <= 'F')
+                curr = (c - 'A' + 10);
+
+            else
+                throw new IllegalArgumentException("Invalid UUID string: "+name);
+
+            curr <<= 4;
+
+            c = name.charAt(++i);
+
+            if (c >= '0' && c <= '9')
+                curr |= (c - '0');
+
+            else if (c >= 'a' && c <= 'f')
+                curr |= (c - 'a' + 10);
+
+            else if (c >= 'A' && c <= 'F')
+                curr |= (c - 'A' + 10);
+
+            else
+                throw new IllegalArgumentException("Invalid UUID string: "+name);
+
+            if (j < 8)
+                hi = (hi << 8) | curr;
+
+            else
+                lo = (lo << 8) | curr;
+
+            ++i;
+        } // for
+
+        return new UUID(hi, lo);
     }
 
     // Field Accessor Methods
@@ -373,17 +418,27 @@
      * @return  A string representation of this {@code UUID}
      */
     public String toString() {
-        return (digits(mostSigBits >> 32, 8) + "-" +
-                digits(mostSigBits >> 16, 4) + "-" +
-                digits(mostSigBits, 4) + "-" +
-                digits(leastSigBits >> 48, 4) + "-" +
-                digits(leastSigBits, 12));
+        char[] arr = new char[36];
+        arr[8] = arr[13] = arr[18] = arr[23] = '-';
+        long msb = mostSigBits;
+        long lsb = leastSigBits;
+        // upper 32 bit of MSB
+        digits(msb >> 32, 8, arr, 0);
+        // upper 16 bit of lower 32 bit of MSB
+        digits(msb >> 16, 4, arr, 9);
+        // lower 16 bit of lower 32 bit of MSB
+        digits(msb, 4, arr, 14);
+        // upper 16 bit of LSB
+        digits(lsb, 4, arr, 19);
+        // lower 48 bit of LSB
+        digits(lsb, 12, arr, 24);
+        return new String(arr);
     }
 
-    /** Returns val represented by the specified number of hex digits. */
-    private static String digits(long val, int digits) {
-        long hi = 1L << (digits * 4);
-        return Long.toHexString(hi | (val & (hi - 1))).substring(1);
+    private static final char[] HEX = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+    private void digits(long v, int digits, char[] arr, int off) {
+        for ( ; digits > 0 ; off++ )
+            arr[off] = HEX[ (int)(v&15) ];
     }
 
     /**





More information about the core-libs-dev mailing list