On Mon, 29 Sep 2025 15:08:14 GMT, Kieran Farrell <[email protected]> wrote:
>> With the recent approval of UUIDv7 >> (https://datatracker.ietf.org/doc/rfc9562/), this PR aims to add a new >> static method UUID.timestampUUID() which constructs and returns a UUID in >> support of the new time generated UUID version. >> >> The specification requires embedding the current timestamp in milliseconds >> into the first bits 0–47. The version number in bits 48–51, bits 52–63 are >> available for sub-millisecond precision or for pseudorandom data. The >> variant is set in bits 64–65. The remaining bits 66–127 are free to use for >> more pseudorandom data or to employ a counter based approach for increased >> time percision >> (https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7). >> >> The choice of implementation comes down to balancing the sensitivity level >> of being able to distingush UUIDs created below <1ms apart with performance. >> A test simulating a high-concurrency environment with 4 threads generating >> 10000 UUIDv7 values in parallel to measure the collision rate of each >> implementation (the amount of times the time based portion of the UUID was >> not unique and entries could not distinguished by time) yeilded the >> following results for each implemtation: >> >> >> - random-byte-only - 99.8% >> - higher-precision - 3.5% >> - counter-based - 0% >> >> >> Performance tests show a decrease in performance as expected with the >> counter based implementation due to the introduction of synchronization: >> >> - random-byte-only 143.487 ± 10.932 ns/op >> - higher-precision 149.651 ± 8.438 ns/op >> - counter-based 245.036 ± 2.943 ns/op >> >> The best balance here might be to employ a higher-precision implementation >> as the large increase in time sensitivity comes at a very slight performance >> cost. > > Kieran Farrell has updated the pull request incrementally with one additional > commit since the last revision: > > missing semicolon src/java.base/share/classes/java/util/UUID.java line 185: > 183: > 184: /** > 185: * Static factory to create a version 7 (time-based) {@code UUID} > with a user-supplied Would it be better to reword this method javadoc to something like: /** * Creates a {@code UUIDv7} {@code UUID} from the given Unix Epoch timestamp. * * The returned {@code UUID} will have the given {@code timestamp} in * the first 6 bytes, followed by the version and variant bits representing {@code UUIDv7}, * and the remaining bytes will contain random data from a cryptographically strong * pseudo-random number generator. * * @apiNote {@code UUIDv7} values are created by allocating a Unix timestamp in milliseconds * in the most significant 48 bits and filling the remaining 74 bits, excluding the required * version and variant bits, with random bits. As such, this method rejects {@code timestamp} * values that do not fit into 48 bits. * * @param timestamp the number of milliseconds since midnight 1 Jan 1970 UTC, * leap seconds excluded. * * @return a {@code UUID} constructed using the given {@code timestamp} * * @throws IllegalArgumentException if the timestamp is negative or greater than {@code 281474976710655L} * * @spec https://www.rfc-editor.org/rfc/rfc9562.html * RFC 9562 Universally Unique IDentifiers (UUIDs) * * @since 26 * */ (the text used for the apiNote is borrowed from the RFC) src/java.base/share/classes/java/util/UUID.java line 207: > 205: * > 206: * @since 26 > 207: * */ Nit - the `*/` should be on the next line. src/java.base/share/classes/java/util/UUID.java line 208: > 206: * @since 26 > 207: * */ > 208: public static UUID epochMillis(long timestamp) { Now that we have settled on which API to expose, would it be better to rename this new method to `fromEpochMillis(...)`? This class already has a `fromString(...)` API, so `fromEpochMillis(...)` would fit in with that style and would be a bit more precise too, I think. src/java.base/share/classes/java/util/UUID.java line 210: > 208: public static UUID epochMillis(long timestamp) { > 209: if ((timestamp >> 48) != 0) { > 210: throw new IllegalArgumentException("Timestamp must be an > unsigned 48-bit Unix Epoch time in milliseconds."); Might be a good idea to include the passed `timestamp` value in the exception message to help identify what the incorrect value was. For example, maybe change the exception message to something like `"timestamp value " + timestamp + " exceeds 48 bits"` ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/25303#discussion_r2389949074 PR Review Comment: https://git.openjdk.org/jdk/pull/25303#discussion_r2389950223 PR Review Comment: https://git.openjdk.org/jdk/pull/25303#discussion_r2389954030 PR Review Comment: https://git.openjdk.org/jdk/pull/25303#discussion_r2389956994
