Add a seedable UUIDv4 generator
What does this MR do?
This MR adds a seedable UUIDv4 generator function, which has the signature:
uuids()
uuids(options)
options
is an object with the following optional properties:
Option | Description |
---|---|
seeds |
An array of integer or string values to seed the internal PRNG with. |
count |
The number of UUIDs to generate |
The return value is:
Array[<UUID>]
Why
As we're working toward a solution to #33867 and with an eye forward to uniquely identifying everything, it will help to be able to have a standard, unique ID generator.
UUID is - hands-down - the world's most popular and agreed-upon unique ID format.
Internally, it uses a Mersenne Twister to generate "random" numbers (not cryptographically secure random, but good enough for string IDs). A Mersenne Twister is by far the best (computationally cheap) Pseudo-Random Number Generator that fixes most problems with other PRNGs (and passes most statistical tests for randomness).1
Having this tool available to us will pave the path for more performant applications on the front end.
Screenshots
N/A, all ~backstage
Does this MR meet the acceptance criteria?
Conformity
- [-] Changelog entry
- [-] Documentation (if required)
-
Code review guidelines -
Merge request performance guidelines -
Style guides - [-] Database guides
- [-] Separation of EE specific content
Availability and Testing
One thing to note: a Mersenne Twister is a number generator. As such, it is not especially fast.
That said, we're talking "able to generate 1,500,000+ numbers per second" "slow", not "it takes 1 second to generate a number" slow.
The internal Mersenne Twister is asked to generate 16 numbers for every UUID requested (this is how many random numbers the UUID library needs to properly generate a value).
Due to this, the generation of one UUID takes around 0.006 milliseconds (6 microseconds).
Raw Node (14.3.0) performance data from inside our test suite
{
"1m": {
start: 1060.470398,
end: 6836.521165,
total: 5776.050767000001,
perUuid: 0.005776050767,
perNumber: 0.0003610031729375
},
"100k": {
start: 1122.07602,
end: 1765.2996640000001,
total: 643.2236440000001,
perUuid: 0.006432236440000002,
perNumber: 0.0004020147775000001
},
"10k": {
start: 1000.047282,
end: 1058.441528,
total: 58.39424600000007,
perUuid: 0.0058394246000000065,
perNumber: 0.0003649640375000004
},
"1k": {
start: 971.93944,
end: 978.894084,
total: 6.95464400000003,
perUuid: 0.006954644000000031,
perNumber: 0.0004346652500000019
}
}
Previous results before some optimizations
{
"1m": {
"start": 1066.507532,
"end": 11103.974058,
"total": 10037.466526,
"uuid": 0.010037466526,
"number": 0.000627341657875
},
"100k": {
"start": 11104.019287,
"end": 12143.217934,
"total": 1039.198647000001,
"uuid": 0.01039198647000001,
"number": 0.0006494991543750006
},
"10k": {
"start": 12143.233454,
"end": 12243.383197,
"total": 100.14974299999994,
"uuid": 0.010014974299999995,
"number": 0.0006259358937499997
}
}
Number of UUIDs Requested | Time | Time per UUID | Time per Random Number |
---|---|---|---|
1,000,000 | 5776ms | 5.78μs | 361ns |
100,000 | 643ms | 6.43μs | 402ns |
10,000 | 58ms | 5.84μs | 365ns |
1,000 | 7ms | 6.95μs | 435ns |
Previous performance before optimizations
Number of UUIDs Requested | Time | Time per UUID | Time per Random Number |
---|---|---|---|
1,000,000 | 10037ms | 10.037μs | 627ns |
100,000 | 1039ms | 10.392μs | 649ns |
10,000 | 100ms | 10.015μs | 626ns |
Removed internal `mersenne_twister`
Number of UUIDs Requested | Time | Time per UUID | Time per Random Number |
---|---|---|---|
1,000,000 | 4983ms | 4.983μs | 311ns |
100,000 | 493ms | 4.93μs | 308ns |
10,000 | 58ms | 5.8μs | 363ns |
We can expect reasonable performance when generating <=50,000 UUIDs, which should be sufficient for the vast majority of use-cases. Future improvements could target the Mersenne Twister or UUID generator for optimizations.
-
Review and add/update tests for this feature/bug. Consider all test levels. See the Test Planning Process. -
Tested in all supported browsers - [-] Informed Infrastructure department of a default or new setting change, if applicable per definition of done
Security
If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:
- [-] Label as security and @ mention
@gitlab-com/gl-security/appsec
- [-] The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
- [-] Security reports checked/validated by a reviewer from the AppSec team