diff --git a/README.md b/README.md
index ab5b204..d684e53 100644
--- a/README.md
+++ b/README.md
@@ -118,6 +118,8 @@ This implementation does away with the string concatenation (and resulting strin
| `UUID#fromString(String)` | 2,613,730 UUIDs/second | ± 25,278 UUIDs/second |
| `FastUUID#parseUUID(String)` | 16,796,302 UUIDs/second | ± 191,695 UUIDs/second |
+Java 15 uses a [much improved method](https://github.com/openjdk/jdk/commit/ebadfaeb2e1cc7b5ce5f101cd8a539bc5478cf5b) to parse UUIDs from strings. As a result, we just pass calls to `FastUUID#parseUUID(String)` through to `UUID#fromString(String)` under Java 15 and newer.
+
### UUIDs to strings
We've shown that we can significantly improve upon the stock `UUID#fromString(String)` implementation. Can we achieve similar gains in going from a `UUID` to a `String`? Let's take a look at the stock implementation of `UUID#toString()` from Java 8:
diff --git a/pom.xml b/pom.xml
index e27a634..245e0b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,21 +48,21 @@
junit
junit
- 4.13.1
+ 4.13.2
test
org.openjdk.jmh
jmh-core
- 1.21
+ 1.32
test
org.openjdk.jmh
jmh-generator-annprocess
- 1.21
+ 1.32
test
@@ -110,7 +110,7 @@
org.openjdk.jmh
jmh-generator-annprocess
- 1.21
+ 1.32
diff --git a/src/benchmark/java/com/eatthepath/UUIDBenchmark.java b/src/benchmark/java/com/eatthepath/UUIDBenchmark.java
index 025097e..21e88ae 100644
--- a/src/benchmark/java/com/eatthepath/UUIDBenchmark.java
+++ b/src/benchmark/java/com/eatthepath/UUIDBenchmark.java
@@ -40,7 +40,8 @@ public class UUIDBenchmark {
private final UUID[] uuids = new UUID[PREGENERATED_UUID_COUNT];
private final String[] uuidStrings = new String[PREGENERATED_UUID_COUNT];
- private int i = 0;
+ // Using a long here because on very fast machines the int will overflow
+ private long i = 0;
@Setup
public void setup() {
@@ -54,21 +55,27 @@ public void setup() {
@Benchmark
public UUID benchmarkUUIDFromString() {
- return UUID.fromString(this.uuidStrings[this.i++ % PREGENERATED_UUID_COUNT]);
+ return UUID.fromString(this.uuidStrings[(int) (this.i++ % PREGENERATED_UUID_COUNT)]);
}
@Benchmark
public UUID benchmarkUUIDFromFastParser() {
- return FastUUID.parseUUID(this.uuidStrings[this.i++ % PREGENERATED_UUID_COUNT]);
+ return FastUUID.parseUUID(this.uuidStrings[(int) (this.i++ % PREGENERATED_UUID_COUNT)]);
+ }
+
+ // Checking if type-check to String won't affect performance
+ @Benchmark
+ public UUID benchmarkUUIDFromCharSequenceFastParser() {
+ return FastUUID.parseUUID((CharSequence) this.uuidStrings[(int) (this.i++ % PREGENERATED_UUID_COUNT)]);
}
@Benchmark
public String benchmarkUUIDToString() {
- return this.uuids[this.i++ % PREGENERATED_UUID_COUNT].toString();
+ return this.uuids[(int) (this.i++ % PREGENERATED_UUID_COUNT)].toString();
}
@Benchmark
public String benchmarkFastParserToString() {
- return FastUUID.toString(this.uuids[this.i++ % PREGENERATED_UUID_COUNT]);
+ return FastUUID.toString(this.uuids[(int) (this.i++ % PREGENERATED_UUID_COUNT)]);
}
}
diff --git a/src/main/java/com/eatthepath/uuid/FastUUID.java b/src/main/java/com/eatthepath/uuid/FastUUID.java
index 451839e..6c356cf 100644
--- a/src/main/java/com/eatthepath/uuid/FastUUID.java
+++ b/src/main/java/com/eatthepath/uuid/FastUUID.java
@@ -41,6 +41,7 @@
public class FastUUID {
private static final boolean USE_JDK_UUID_TO_STRING;
+ private static final boolean USE_JDK_UUID_FROM_STRING;
static {
int majorVersion = 0;
@@ -53,6 +54,7 @@ public class FastUUID {
}
USE_JDK_UUID_TO_STRING = majorVersion >= 9;
+ USE_JDK_UUID_FROM_STRING = majorVersion >= 15;
}
private static final int UUID_STRING_LENGTH = 36;
@@ -107,6 +109,35 @@ private FastUUID() {
* described in {@link UUID#toString()}
*/
public static UUID parseUUID(final CharSequence uuidSequence) {
+ if (USE_JDK_UUID_FROM_STRING && uuidSequence instanceof String) {
+ // OpenJDK 15 and newer use a faster method for parsing UUIDs
+ return UUID.fromString((String) uuidSequence);
+ }
+
+ return parseUUIDInternal(uuidSequence);
+ }
+
+ /**
+ * Parses a UUID from the given string. The string must represent a UUID as described in
+ * {@link UUID#toString()}.
+ *
+ * @param uuidString the string from which to parse a UUID
+ *
+ * @return the UUID represented by the given string
+ *
+ * @throws IllegalArgumentException if the given string does not conform to the string representation as
+ * described in {@link UUID#toString()}
+ */
+ public static UUID parseUUID(final String uuidString) {
+ if (USE_JDK_UUID_FROM_STRING) {
+ // OpenJDK 15 and newer use a faster method for parsing UUIDs
+ return UUID.fromString(uuidString);
+ }
+
+ return parseUUIDInternal(uuidString);
+ }
+
+ private static UUID parseUUIDInternal(final CharSequence uuidSequence) {
if (uuidSequence.length() != UUID_STRING_LENGTH ||
uuidSequence.charAt(8) != '-' ||
uuidSequence.charAt(13) != '-' ||