Skip to content

perf: optimize regex, remove uuid()#1044

Merged
overbalance merged 4 commits intomainfrom
overbalance/perf/cpu-bottleneck-optimizations
Jan 7, 2026
Merged

perf: optimize regex, remove uuid()#1044
overbalance merged 4 commits intomainfrom
overbalance/perf/cpu-bottleneck-optimizations

Conversation

@overbalance
Copy link
Copy Markdown
Member

@overbalance overbalance commented Jan 6, 2026

What problem is this solving?

Reduces SDK CPU overhead by optimizing hot paths identified via performance profiling.

Short description of changes

  • Replace regex .exec() with url.includes('://') in isNetworkSpan type guard
  • Adopt OTel byte-to-hex UUID algorithm (from opentelemetry-js#6209), removing uuid dependency
  • Use native crypto.getRandomValues() instead of uuid npm package
  • Bump heap threshold 15→16 MB to reduce test flakiness

Testing

  • All 565 unit tests pass
  • Performance tests pass with ~14% task duration improvement

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 6, 2026

Chrome DevTools Protocol Tracing (Script: 106.76ms, Heap: 13.94MB)
Number of Requests Size of Requests Script Duration Task Duration Heap Used Size
Requests +3 requests +29.68 KB
Page Loaded +16.57 ms +9.70 ms +0.94 MB
Generate 100 fetch requests +15.52 ms +64.14 ms +1.97 MB
Generate 100 XHR requests +39.07 ms +99.08 ms +2.36 MB
Click 100 buttons and generate 100 logs +27.78 ms +23.62 ms +2.95 MB
Throw a 100 exceptions -0.07 ms +11.38 ms +2.51 MB
End Session +7.89 ms +15.56 ms +3.22 MB
Total +3 requests +29.68 KB +106.76 ms +223.47 ms +13.94 MB
Lighthouse (Script Eval: 49.98ms)
Difference Description
Total Blocking Time 0 ms Difference in Total Blocking Time: Sum of all time periods between FCP and Time to Interactive, when task length exceeded 50ms, expressed in milliseconds. Learn more about the Total Blocking Time metric.
Main Thread Time +57.61 ms Difference in Main Thread Time: Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this. Learn how to minimize main-thread work
Script Evaluation Time +49.98 ms Difference in Script Evaluation Time: Consider reducing the time spent parsing, compiling, and executing JS. You may find delivering smaller JS payloads helps with this. Learn how to reduce Javascript execution time.
Platform Tests (vite-7 gzip: 47.60KB)

vite-7 Platform Tests

Total Uncompressed Size Total Gzip Size
vite-7 - esnext +163.90 KB +47.60 KB
vite-7 - es2015 +170.67 KB +49.25 KB

vite-otel-latest Platform Tests

Total Uncompressed Size Total Gzip Size
vite-otel-latest - esnext +162.97 KB +49.35 KB
vite-otel-latest - es2015 +169.66 KB +50.95 KB

webpack-5 Platform Tests

Total Uncompressed Size Total Gzip Size
webpack-5 - esnext +120.06 KB +42.58 KB
webpack-5 - es2015 +121.18 KB +44.09 KB

Comment thread src/utils/generateUUID.ts
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be concerned about replacing the uuid library with our own implementation without more extensive testing around the values we're getting out being similarly random. Could you also speak to where the performance gains are relative to https://github.com/uuidjs/uuid/blob/main/src/v4.ts ?

Copy link
Copy Markdown
Member Author

@overbalance overbalance Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I benchmarked more thoroughly and the performance is negligible:

  Browser Benchmark (Chromium)

  | Implementation         | ops/sec | ns/op | vs uuid |
  |------------------------|---------|-------|---------|
  | uuid library           | 925K    | 1,081 | 1.00x   |
  | Math.random            | 8.7M    | 115   | 9.42x   |
  | crypto.getRandomValues | 1.1M    | 930   | 1.16x   |

Absolute impact per 1,000 spans:
  - uuid library: 1.1ms
  - Math.random: 0.1ms
  - crypto.getRandomValues: 0.9ms

What we do gain:

  1. Removing uuid means one less third-party lib
  2. crypto is more secure than Math.random and slightly faster than uuid npm package

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we know why this ends up faster than the uuid package? It is also using crypto.getRandomValues: https://github.com/uuidjs/uuid/blob/main/src/rng-browser.ts#L18

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surprisingly it's the string manipulation actions to change case and add/remove hyphens.

@overbalance overbalance requested a review from jpmunz January 6, 2026 20:11
@overbalance overbalance changed the title perf: optimize CPU-intensive operations perf: optimize regex, remove uuid() Jan 6, 2026
Comment thread src/utils/generateUUID.ts
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we know why this ends up faster than the uuid package? It is also using crypto.getRandomValues: https://github.com/uuidjs/uuid/blob/main/src/rng-browser.ts#L18

Comment thread src/utils/generateUUID.ts
export const generateUUID = () => uuid().replace(/-/g, '').toUpperCase();
// Pre-computed uppercase hex lookup - faster than toString(16) in browsers
const HEX: string[] = Array.from({ length: 256 }, (_, i) =>
i.toString(16).padStart(2, '0').toUpperCase(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would we need the i + 0x100 piece that is being done in https://github.com/uuidjs/uuid/blob/main/src/stringify.ts#L10 as well? Or is that handled by padStart?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, padStart gives the same 2 digit guarantee

@overbalance overbalance requested a review from jpmunz January 7, 2026 15:22
@overbalance overbalance merged commit 1f62d87 into main Jan 7, 2026
17 checks passed
@overbalance overbalance deleted the overbalance/perf/cpu-bottleneck-optimizations branch January 7, 2026 19:05
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.

2 participants