Description
Operating System
MacOS 13.6.1
Browser Version
120.0.6099.71
Firebase SDK Version
10.7.1
Firebase SDK Product:
Performance
Describe your project's tooling
Static site
Describe the problem
I've been using firebase-performance-standalone.js
on https://www.paulirish.com/
Recently I added a feature (cough easter egg cough) that uses/abuses User Timing to paint a cute little thing when you profile the page in chrome devtools performance panel. (Timings track).. To do that I issue ~1000 performance.measure()
s.
On my machine, creating all the measures takes ~10ms. But then later I see the firebase SDK logging all them with createUserTimingTrace()
and that takes ~230ms.
This may seem like an excessive amount of user timing measures, but.. I know some frameworks like to use measures quite heavily, so 500-1000 may not be all that unexpected.
Steps and code to reproduce issue
- Open https://www.paulirish.com/
- open devtools Performance panel.
- record and reload the page.
- look at the trace. Notice the large JS cost at the end. That's the firebase sdk perf component.
I built the SDK locally so I could profile a debug build.. Here's my three major findings:
The navigator.cookieEnabled
read is surprisingly costly. (Sorry, probably something Chrome can try to optimize, too). That value should be cached somewhere. (I can't imagine it changing mid session..)

sendTraceLog
uses setTimeout(fn, 0)
on every invocation. Installing each timer is costly.
You could debounce or coalesce these sendLogs some other way. (or maybe the serialization happens after addToQueue, which would let your queue create this yielding rather than the yield on every trace.
With the current setup (setTimeout 0 on every trace), things take 600ms (I have CPU throttling applied now). When I just sendLog directly, it's ~400ms. Yielding is the responsible thing to do!, for sure.. But.. not this frequently. :)
performance.getEntriesByType()
is called for each entry being processed. A small refactor would avoid asking the DOM api for data we had two methods ago. This cuts ~400ms down to ~170ms.

There's plenty more low hanging fruit if you profile with cpu throttling on. Eg getApplicationInfo
and requiredApisAvailable
return values should probably be cached. I'm happy to help if you wanna poke at this some. (I'm on the DevTools team)