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

Mike Duigou mike.duigou at oracle.com
Fri Nov 15 22:09:20 UTC 2013


Hi Robert;

As mentioned in another thread with Steven Schlansker there is a patch in progress with similar goals. I will look at your patch and see how much overlap there is and merge in any relevant parts. This improvement won't make it into Java 8 but will be implemented early in the Java 9 lifecycle and can be backported to Java 8 updates.

Thanks!

Mike


On Nov 6 2013, at 17:19 , Robert Stupp <snazy at gmx.de> wrote:

> 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