-
-
Notifications
You must be signed in to change notification settings - Fork 906
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
feat: slightly improved v1 perf #453
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ let _lastNSecs = 0; | |
// See https://github.com/uuidjs/uuid for API details | ||
function v1(options, buf, offset) { | ||
let i = (buf && offset) || 0; | ||
const b = buf || []; | ||
const b = buf || new Array(16); | ||
ctavan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
options = options || {}; | ||
let node = options.node || _nodeId; | ||
|
@@ -27,6 +27,7 @@ function v1(options, buf, offset) { | |
// system entropy. See #189 | ||
if (node == null || clockseq == null) { | ||
const seedBytes = options.random || (options.rng || rng)(); | ||
|
||
if (node == null) { | ||
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) | ||
node = _nodeId = [ | ||
|
@@ -38,6 +39,7 @@ function v1(options, buf, offset) { | |
seedBytes[5], | ||
]; | ||
} | ||
|
||
if (clockseq == null) { | ||
// Per 4.2.2, randomize (14 bit) clockseq | ||
clockseq = _clockseq = ((seedBytes[6] << 8) | seedBytes[7]) & 0x3fff; | ||
|
@@ -70,7 +72,9 @@ function v1(options, buf, offset) { | |
|
||
// Per 4.2.1.2 Throw error if too many uuids are requested | ||
if (nsecs >= 10000) { | ||
throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); | ||
const error = new Error("uuid.v1(): Can't create more than 10M uuids/sec"); | ||
error.code = 'UUID_V1_LIMIT_PER_SEC'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we keep this, I suggest to align it with Node.js error code naming and call ist something like Since, as explained below, this is the only runtime error of this library, I would prefer to revert this for now (or extract this into a separate PR so we can merge the perf optimization first and think about error codes a bit more). |
||
throw error; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Revert.
If this is needed (which I'm on the fence about, and 'would like to get @ctavan's opinion here) I'd suggest something along these lines... // Create minimal Error subclass (Define in UuidRateError.js file so it can be exported as part of src/index.js?)
export class UuidRateError extends Error {}
// ... Throw in this file when rate exceeded ...
throw new UuidRateError(`UUID creation rate limit exceeded`)
// ... use `instanceof` elsewhere to detect...
import {v1 as uuidv1, UuidRateError} from 'uuid'
// ...
try {
uuidv1()
} catch (err) {
if (err instanceof UuidRateError) // etc...
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @broofa it will be harder for library users. They will need to guess that non-standard exceptions are thrown. When it is already accepted in nodejs to identify an error by code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Huh... I wasn't aware |
||
} | ||
|
||
_lastMSecs = msecs; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revert?
Why is this needed? Are we hitting the rate limit with our benchmark? If so, that's kind of cool... but it also invalidates the benchmark so should probably be
abort()
ed with an appropriate message.Note: Silently dropping errors in
catch
blocks is a very strong code smell. At a minimum, there should be a comment explaining the rationale for it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@broofa periodically the limit is exceeded on my machine and an exception is thrown.
This is strange, but the block
try/catch
does not affect the performance %)If an exception is thrown, the following tests will fail.
In new versions of nodejs (v13.14.0), performance is even higher. Exceptions are thrown more often.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is surprising. It's the first time I've seen this limit hit in the real world. (I added that rate check years ago to comply with the spec, never really expecting to hit it in practice.) What hardware are you running on if I may ask?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@broofa I have my own computer on which I run tests (nodejs v12.16.3):
CPU: AMD Ryzen 7 1700
RAM: 32 Gb 2999 MHz
Typically, an exception occurs the first few times the benchmark is launched. And then the testing goes fine. Maybe it's a bug. (With
try/catch
I never get a performance close or higher to 10M)The exception is much more likely to occur on new versions of nodejs (v13). Because the overall performance of the library is increasing.
On nodejs v13 I usually get performance:
uuidv1() fill existing array x 8,777,105 ops/sec ±0.82% (96 runs sampled)
.