-
-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove the need for shuffle in UuidUtil.mathRNG #59
Comments
I should add that the consequence of removing the shuffle also for when a |
This is fantastic, and thank you for taking the time to dig this info up and relay the information. I don't believe I am concerned about backwards compatibility for 3.x since i did a lot of breaking changes already. This also primarily powers v4 numbers, which are primarily used for completely random UUIDs every time. Seeds are rarely used with v4 in production use-cases. I am ok with the consequences. I will be honest, I have made changes that changed the UUID outputs for v4 in the past. I am currently focused on work stuff, but I will merge this and create a release in a few hours. Again, thank you very much for the PR and figuring this out, this is good info to know. |
Thanks for the fast response. 👍 And just take the time. This is not really that urgent. I just stumbled into this implementation and was kinda puzzled about the shuffle and the reasons behind it. :) |
Just released 3.0.1 with your fix. Thanks again! |
The fix for #46 introduced the following in
UuidUtil.mathRNG
:This solution is not really optimal but was properly introduced because of missing knowledge about the underlying problem which is misuse of the
Random
class. This can be expected since the Dart SDK documentation forRandom
is not really that specific about how to use it.The real problem in #46 is that we are creating a new
Random()
object every time we callUuidUtil.mathRNG
. When we create aRandom()
object, The Dart VM are using an internal random generator to generate a seed for our ownRandom()
instance. ForRandom()
, this seed is 32 bit long. The implementation for this can be found here:https://github.com/dart-lang/sdk/blob/fd81b73e67051a7ac06669a01ec32082ced0dc4f/sdk/lib/_internal/vm/lib/math_patch.dart#L183
32 bit of randomness is not really that great (two Random objects with same seed will produce the same number sequence) and will open op for problems if we create a lot of
Random()
objects. But the random generator behindRandom()
is well implemented without the worry of repeating patterns. So what we should do instead is just create a single instance for our UUID library and reuse this.An example can be see here:
The reason why calling
shuffle
"fixes" the problem, is because shuffle are creating its ownRandom
object every time:https://github.com/dart-lang/sdk/blob/4a484c88e13ef0f4847daba3c25fa22dbe933a08/sdk/lib/collection/list.dart#L363
This is really not what big of a problem since we are not expecting
shuffle
to be based on great randomness (and if we do, we are properly usingRandom.secure()
. But since we are creating anotherRandom
object, and uses that for shuffle, we do make it a lot more rare that we get two 32 bit seeds in a row which we have previous seen.But the use of
shuffle
is really just needless use of CPU cycles for something which can be fixed by creating astatic final
random generator.(My change does also add a
static final
forRandom.secure()
. The Dart VM is implemented to call the OS for random numbers for all numbers generated withRandom.secure()
so we don't have the same seed problem. But both for consistency, and because there can be some overhead, we should also just cache this random generator instance.)The text was updated successfully, but these errors were encountered: