Skip to content
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

perf(common): faster random string generator #10825

Merged

Conversation

H4ad
Copy link
Contributor

@H4ad H4ad commented Jan 8, 2023

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior?

The method randomStringGenerator is implemented with uuid package, which is slow when we compare with other package like uid:

uuid x 4,724,786 ops/sec ±2.35% (81 runs sampled)
nanoid x 2,880,683 ops/sec ±2.16% (79 runs sampled)
uid x 37,413,066 ops/sec ±1.91% (85 runs sampled)
Fastest is uid

Benchmark

This method is also used inside instance-wrapper.ts, which is instantiated a lot during the initialization of NestJS, above the profiling information:

 [Shared libraries]:
   ticks  total  nonlib   name
  35505   66.5%          /home/h4ad/.asdf/installs/nodejs/12.22.12/bin/node
    725    1.4%          /usr/lib/x86_64-linux-gnu/libc-2.31.so
     18    0.0%          /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
      3    0.0%          [vdso]

[JavaScript]:
   ticks  total  nonlib   name
    435    0.8%    2.5%  LazyCompile: *OrdinaryGetMetadata /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/reflect-metadata/Reflect.js:600:37
    316    0.6%    1.8%  LazyCompile: *getAllFilteredMethodNames /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/@nestjs/core/metadata-scanner.js:14:31
    307    0.6%    1.8%  LazyCompile: *reflectKeyMetadata /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/@nestjs/core/scanner.js:150:23
    264    0.5%    1.5%  LazyCompile: *reflectDynamicMetadata /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/@nestjs/core/scanner.js:117:27
    251    0.5%    1.5%  LazyCompile: *next /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/iterare/lib/iterate.js:20:9
    217    0.4%    1.3%  LazyCompile: *_object /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/object-hash/index.js:192:22
    213    0.4%    1.2%  LazyCompile: *loadInstance /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/@nestjs/core/injector/injector.js:30:23
    177    0.3%    1.0%  LazyCompile: *_string /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/object-hash/index.js:304:22
    175    0.3%    1.0%  LazyCompile: *__rest /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/tslib/tslib.js:85:23
    174    0.3%    1.0%  LazyCompile: *unsafeStringify /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/uuid/dist/stringify.js:23:25

Source

The last call unsafeStringify is the problem.

Issue Number: N/A

What is the new behavior?

I added a new package called uid based on the previous benchmark to generate faster random strings.

Now, when we see the profiling information:

[Shared libraries]:
   ticks  total  nonlib   name
  32573   66.1%          /home/h4ad/.asdf/installs/nodejs/12.22.12/bin/node
    696    1.4%          /usr/lib/x86_64-linux-gnu/libc-2.31.so
      6    0.0%          /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
      2    0.0%          [vdso]

 [JavaScript]:
   ticks  total  nonlib   name
    468    1.0%    2.9%  LazyCompile: *OrdinaryGetMetadata /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/reflect-metadata/Reflect.js:600:37
    320    0.6%    2.0%  LazyCompile: *getAllFilteredMethodNames /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/@nestjs/core/metadata-scanner.js:14:31
    274    0.6%    1.7%  LazyCompile: *reflectKeyMetadata /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/@nestjs/core/scanner.js:150:23
    249    0.5%    1.6%  LazyCompile: *next /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/iterare/lib/iterate.js:20:9
    237    0.5%    1.5%  LazyCompile: *applyDefaults /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/object-hash/index.js:61:23
    205    0.4%    1.3%  LazyCompile: *write /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/object-hash/index.js:169:23
    192    0.4%    1.2%  LazyCompile: *loadInstance /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/@nestjs/core/injector/injector.js:30:23
    186    0.4%    1.2%  LazyCompile: *reflectDynamicMetadata /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/@nestjs/core/scanner.js:117:27
    176    0.4%    1.1%  LazyCompile: *_string /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/object-hash/index.js:304:22
    165    0.3%    1.0%  LazyCompile: *__rest /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/tslib/tslib.js:85:23

Source

We have almost 3k ticks less than the previous version using uuid, when we search for uid, we found this line:

23    0.0%    0.1%  LazyCompile: *uid /home/h4ad/Projects/opensource/performance-analysis/test-performance-nestjs/node_modules/uid/dist/index.js:4:13  

Much faster compared to 174 ticks from the previous package.

From my tests, creating 10,000 times an API with 20 modules, I went from 7.1213ms to 6.451ms to initialize NestJS.
This value can fluctuate depending on the machine and how many times you run but my baseline of improvement was the profiler information.

Benchmark.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

@H4ad H4ad mentioned this pull request Jan 10, 2023
1 task
@kamilmysliwiec kamilmysliwiec merged commit cb4b41f into nestjs:master Feb 1, 2023
@H4ad H4ad deleted the perf/random-string-generator branch February 1, 2023 13:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants