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

Reply via email to