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

Reply via email to