On Tue, 20 May 2025 13:35:32 GMT, kieran-farrell <d...@openjdk.org> wrote:
>> src/java.base/share/classes/java/util/UUID.java line 219: >> >>> 217: randomBytes[8] |= (byte) 0x80; >>> 218: >>> 219: return new UUID(randomBytes); >> >> This could remove the allocation by composing the high and low longs using >> shifts and binary operations and ng.next(). >> Can the sub-microsecond value just be truncated and avoid the expensive >> divide operation? > >> Can the sub-microsecond value just be truncated and avoid the expensive >> divide operation?' > > method 3 of secion 6.2 of > https://www.rfc-editor.org/rfc/rfc9562.html#name-monotonicity-and-counters > states > >> start with the portion of the timestamp expressed as a fraction of the >> clock's tick value (fraction of a millisecond for UUIDv7). Compute the count >> of possible values that can be represented in the available bit space, 4096 >> for the UUIDv7 rand_a field. Using floating point or scaled integer >> arithmetic, multiply this fraction of a millisecond value by 4096 and round >> down (toward zero) to an integer result to arrive at a number between 0 and >> the maximum allowed for the indicated bits, which sorts monotonically based >> on time. ' > > so i think we might have to keep the division? though i re-shuffled the > equation to > > `int nsBits = (int) ((nsTime % 1_000_000) / 1_000_000.0 * 4096);` > > which gives scaled integer division rather than floating point and gave a > very slight imporved perfomance to 143.758 ± 2.135 ns/op > This could remove the allocation by composing the high and low longs using > shifts and binary operations and ng.next(). do you mean to create the UUID using most and least significant bytes? if so, I've tried out some variations, i found creating the 64 bit lsb with ng.nextLong() brings a large pefomance decrease over using the nextBytes method, but the below implemntation keeping with the nextByte(byte[]) api brings a performance increase to 121.128 ± 30.486 ns/op, though the code might appear a little roundabout. public static UUID timestampUUID() { long msTime = System.currentTimeMillis(); long nsTime = System.nanoTime(); // Scale sub-ms nanoseconds to a 12-bit value int nsBits = (int) ((nsTime % 1_000_000L) * 4096L / 1_000_000L); // Compose the 64 most significant bits: [48-bit msTime | 4-bit version | 12-bit nsBits] long mostSigBits = ((msTime & 0xFFFFFFFFFFFFL) << 16) | (0x7L << 12) | nsBits; // Generate 8 random bytes for least significant bits byte[] randomBytes = new byte[8]; SecureRandom ng = UUID.Holder.numberGenerator; ng.nextBytes(randomBytes); long leastSigBits = 0; for (int i = 0; i < 8; i++) { leastSigBits = (leastSigBits << 8) | (randomBytes[i] & 0xFF); } // Set variant (bits 62–63) to '10' leastSigBits &= 0x3FFFFFFFFFFFFFFFL; leastSigBits |= 0x8000000000000000L; return new UUID(mostSigBits, leastSigBits); } ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/25303#discussion_r2098044396