On Windows (10) (with latest 6 image and VM) `Time microsecondClockValue` returns microseconds, but (presumably the system) cannot give precision beyond 1 second - this will imho need a VM fix;
I find that quite hard to believe and I did not know that. Are you really sure ? That would be terrible. A solution might be to use another clock primitive.
I can also generate about 1.2M UUIDs per second (limited by single core I guess), which means that about every 600-1200 consequential UUIDs will have the same clock value.
I can't follow your reasoning here: if the clock precision would be 1 second, you would get 1.2M consecutive UUIDs with the same clock value, right ?
Whoops, I meant the precision on a millisecond, not second... thus the ~1000k consecutive clock values. The returned value is still in microseconds, but the last 3 digits are fixed (they are different on startup, but same during execution). I faintly remember having the same issue in a different language years ago, because they had different APIs or some bullshit like that. So when I generate e.g. 10 random UUIDs I get: (1 to: 10) collect: [ :i | NeoUUIDGenerator next ]. "an Array( an UUID('349b2ccc-4404-0d00-a8e7-5c9c0ef2da37') an UUID('349b2ccc-4404-0d00-a8e8-2f3a0ef2da37') an UUID('349b2ccc-4404-0d00-a8e9-9e0b0ef2da37') an UUID('349b2ccc-4404-0d00-a8ea-15520ef2da37') an UUID('349b2ccc-4404-0d00-a8eb-fa5c0ef2da37') an UUID('349b2ccc-4404-0d00-a8ec-d25f0ef2da37') an UUID('349b2ccc-4404-0d00-a8ed-6a590ef2da37') an UUID('349b2ccc-4404-0d00-a8ee-3a8d0ef2da37') an UUID('349b2ccc-4404-0d00-a8ef-0ad20ef2da37') an UUID('349b2ccc-4404-0d00-a8f0-7bda0ef2da37'))"
In the unit tests this is verified (that the time value goes forward on consecutive calls).
testTwo*Generator only tests if they are close, not that one is higher than the other, if I add self assert: time2 equals: time1. the test will still pass (but that is already obvious from the list above).
9 & 10 bytes are counter, but 9th bit is rewritten with variant, so the counter is actually 0-255 and not 0-65536.
Yes, but more correctly, the top 2 bits are set to 10, making the range 1 to 2^14 (16384) (instead of 2^16).
Welp, I can't do bit math.
And finally 11 & 12 are random bits (assuming the seeding isn't broken).
The seeding is one aspect (the quality of the seed), the algorithm is another. Note that in the current Random class, the seed is initialised using the clock as well.
The problem with Random is not the time-based initialization, but masking of the initial value (which is mentioned in the originally linked thread on randomness, which fixes itself upon further generations).
So on Windows, the conditional probability that nth and n+256th UUIDs will be identical is imho 1/65536 (assuming they are in the same second, which is easy).
I am pretty/quite sure this is not correct but it would take me much more time to come up with a more correct calculation.
With the actual counter I would have to generate 16384 UUID/milisecond, which unlike 256/ms I cannot do, so it is safe again. :) (well... until Pharo goes multicore)
BTW, you also have to define the context of being the same: the same instance of one NeoUUIDGenerator generating the same UUID, or several different generator instances, in the same image, in different images, on different runs, the same or different machines/networks, ...
On Linux my understanding is that clash can only happen if NTP adjusts my clock during UUID generation (at which point it is same as Windows).
Can UUID clash be achieved on Linux if you deploy copies of the same image and let them all generate UUIDs? (It should be again 1/65536).
Yeah, across machines the last four bytes behave randomly too. Maybe I can get clash if I run two random generators in forks (to fix 14 bits of counter randomness :) ... but no time for that now. :) Peter