On Tue, 20 May 2025 19:32:54 GMT, Roger Riggs <rri...@openjdk.org> wrote:
>>> 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); >> } > > There's no (time-based) relationship between the currentTimeMillis() value > and the nanoTime value. > They are independent clocks and are read separately and are un-correlated. > They won't be usable as lsb of the millis value. > > I'm surprised that the `nextBytes` is slower, since it looks like it calls > `nextLong` and puts it in a newly allocated byte[8]. Normal perf > measurements won't account for the gc overhead to recover it. > > The nsBits computation looks odd, nanoTme returns nanoseconds (10^9), the > remainder (% 1_000_000) is then milliseconds. > 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 Probably because `SecureRandom` gets `#nextLong()` from `Random`, which ends up calling `#next(int)` twice, so it allocates twice. Overriding `#nextLong()` in `SecureRandom` may help a little but will still have to allocate as long as `SecureRandomSpi` is not updated. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/25303#discussion_r2098727054