< prev index next >

src/java.base/share/classes/java/util/UUID.java

Print this page
rev 58200 : 8196334: Optimize UUID#fromString
Reviewed-by: TBD
Contributed-by: plokhotnyuk@gmail.com, jon.chambers@gmail.com, claes.redestad@oracle.com

@@ -179,10 +179,46 @@
         md5Bytes[8]  |= 0x80;  /* set to IETF variant  */
         return new UUID(md5Bytes);
     }
 
     /**
+     * Used by {@code fromString}. While {@code Character.digit(ch, 16)}
+     * could be used to the same effect, benchmarks show specializing
+     * for ASCII hex is still a small but significant gain. We should
+     * examine if {@code Character.digit(ch, 16)} can be optimized and
+     * this code replaced without adding any overhead.
+     */
+    private static final byte[] NIBBLES = new byte[256];
+
+    static {
+        byte[] ns = NIBBLES;
+        java.util.Arrays.fill(ns, (byte) -1);
+        ns['0'] = 0;
+        ns['1'] = 1;
+        ns['2'] = 2;
+        ns['3'] = 3;
+        ns['4'] = 4;
+        ns['5'] = 5;
+        ns['6'] = 6;
+        ns['7'] = 7;
+        ns['8'] = 8;
+        ns['9'] = 9;
+        ns['A'] = 10;
+        ns['B'] = 11;
+        ns['C'] = 12;
+        ns['D'] = 13;
+        ns['E'] = 14;
+        ns['F'] = 15;
+        ns['a'] = 10;
+        ns['b'] = 11;
+        ns['c'] = 12;
+        ns['d'] = 13;
+        ns['e'] = 14;
+        ns['f'] = 15;
+    }
+
+    /**
      * Creates a {@code UUID} from the string standard representation as
      * described in the {@link #toString} method.
      *
      * @param  name
      *         A string that specifies a {@code UUID}

@@ -193,10 +229,44 @@
      *          If name does not conform to the string representation as
      *          described in {@link #toString}
      *
      */
     public static UUID fromString(String name) {
+        if (name.length() == 36) {
+            long ch1 = name.charAt(8);
+            long ch2 = name.charAt(13);
+            long ch3 = name.charAt(18);
+            long ch4 = name.charAt(23);
+            if ((ch1 << 48 | ch2 << 32 | ch3 << 16 | ch4) == 0x2d002d002d002dL) {
+                long msb1 = parse4Nibbles(name, 0);
+                long msb2 = parse4Nibbles(name, 4);
+                long msb3 = parse4Nibbles(name, 9);
+                long msb4 = parse4Nibbles(name, 14);
+                long lsb1 = parse4Nibbles(name, 19);
+                long lsb2 = parse4Nibbles(name, 24);
+                long lsb3 = parse4Nibbles(name, 28);
+                long lsb4 = parse4Nibbles(name, 32);
+                if ((msb1 | msb2 | msb3 | msb4 | lsb1 | lsb2 | lsb3 | lsb4) >= 0) {
+                    return new UUID(msb1 << 48 | msb2 << 32 | msb3 << 16 | msb4,
+                            lsb1 << 48 | lsb2 << 32 | lsb3 << 16 | lsb4);
+                }
+            }
+        }
+        return fromString1(name);
+    }
+
+    private static long parse4Nibbles(String name, int pos) {
+        byte[] ns = NIBBLES;
+        char ch1 = name.charAt(pos);
+        char ch2 = name.charAt(pos + 1);
+        char ch3 = name.charAt(pos + 2);
+        char ch4 = name.charAt(pos + 3);
+        return (ch1 | ch2 | ch3 | ch4) > 0xff ?
+                -1 : ns[ch1] << 12 | ns[ch2] << 8 | ns[ch3] << 4 | ns[ch4];
+    }
+
+    private static UUID fromString1(String name) {
         int len = name.length();
         if (len > 36) {
             throw new IllegalArgumentException("UUID string too large");
         }
 
< prev index next >