JDK-8192784 : Use Long#parseLong(String, int) in UUID#fromString(String) to avoid unnecessary string concatenation
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.util
  • Priority: P4
  • Status: New
  • Resolution: Unresolved
  • Submitted: 2017-11-29
  • Updated: 2023-08-22
Description
A DESCRIPTION OF THE REQUEST :
The current implementation of UUID#fromString(String) is as follows:

```
public static UUID fromString(String name) {
    String[] components = name.split("-");
    if (components.length != 5)
        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 leastSigBits = Long.decode(components[3]).longValue();
    leastSigBits <<= 48;
    leastSigBits |= Long.decode(components[4]).longValue();

    return new UUID(mostSigBits, leastSigBits);
}
```

To convince Long#decode(String) to parse the string as a hexadecimal value, the method prepends "0x" to be beginning of each element of the `components` array. We could instead use `Long#parseLong(String, int)` and avoid five string concatenations per call to `UUID#fromString(String)`:

```
public static UUID fromString(final String name) {
    String[] components = name.split("-");
    if (components.length != 5)
        throw new IllegalArgumentException("Invalid UUID string: "+name);

    long mostSigBits = Long.parseLong(components[0], 16);
    mostSigBits <<= 16;
    mostSigBits |= Long.parseLong(components[1], 16);
    mostSigBits <<= 16;
    mostSigBits |= Long.parseLong(components[2], 16);

    long leastSigBits = Long.parseLong(components[3], 16);
    leastSigBits <<= 48;
    leastSigBits |= Long.parseLong(components[4], 16);

    return new UUID(mostSigBits, leastSigBits);
}
```

JUSTIFICATION :
This approach eliminates five string concatenations per call to `UUID#fromString(String)` and also eliminates some unnecessary unboxing (the calls to `Long#longValue()`). With these changes, jmh shows an improvement in throughput of nearly 50%:

```
Benchmark                                        Mode  Cnt        Score       Error  Units
UuidBenchmark.benchmarkUuidFromString           thrpt   40  1544067.340 ± 39521.275  ops/s
UuidBenchmark.benchmarkUuidFromStringWithRadix  thrpt   40  2284632.364 ± 53192.174  ops/s
```