Thursday, November 12, 2026
HomeCSSMaking Sense of the Efficiency Extensibility API – CSS Wizardry

Making Sense of the Efficiency Extensibility API – CSS Wizardry


in

Internet Efficiency

Written by on CSS Wizardry.

View this web page as Markdown.

Desk of Contents

Impartial writing is dropped at you through my fantastic
Supporters.

  1. Making Your Code a First Class Citizen
  2. efficiency.mark() and efficiency.measure()
  3. The Extensibility API
  4. Minimal Viable Measurement
  5. Maximising the Extensibility API
    1. Tracks and Colors
    2. Observe Teams
  6. Recap
  7. Third Events
  8. Appendix
    1. Useful resource Timing API Instance

Google Chrome lately launched the Efficiency Extensibility
API
, a method
of placing your code front-and-centre in Chrome’s Efficiency panel. Their very own
documentation is considerably dry and doesn’t actually state the advantages or outcomes
very clearly, so I spent a few hours trying into it and listed here are the important thing
takeaways.

Unsure use the Efficiency Extensibility API?
Learn up on the Person Timing
API
’s efficiency.mark() and
efficiency.measure()
first.

Should you:

  • are all in favour of intently profiling particular, atomic elements of your
    utility;

    • you’ll be able to intricately time bare-metal occasions.
  • work in an organisation the place totally different groups contribute totally different code to the
    similar front-end;

    • you’ll be able to create a customized part in DevTools for every workforce.
  • want to collect wealthy (meta)knowledge about key elements of your runtime;
    • you’ll be able to seize arbitrary knowledge as a part of normal APIs.
  • present or eat APIs;
    • you might monitor their response instances with ease and floor that info
      to the front-end and DevTools.
  • keep a 3rd social gathering bundle that may very well be traced;
    • you’ll be able to present clear signposting for key occasions (e.g. hydration) to your
      customers, or;
  • are simply all in favour of efficiency tooling…
    • …this text is for you.

Making Your Code a First Class Citizen

Chrome’s DevTools are
extremely highly effective, and are solely ever getting stronger, however this newest replace
palms a whole lot of management over to us! We will make our personal instrumentation a key
a part of our efficiency profiling expertise.

efficiency.mark() and efficiency.measure()

The Extensibility API is especially helpful in extending the
efficiency.mark() and .measure() Person Timings. Should you aren’t utilizing these
already, try to be. Should you aren’t conversant in them, it’s essential be earlier than
this publish will make sense to you. My 2022 publish Measure What You Influence,
Not What You
Affect
is
a comparatively respectable introduction to the subject, however for now, this straightforward demo
ought to assist:

<script>efficiency.mark('cssStart');</script>

<hyperlink rel=stylesheet href=/app.css>

<script>
  efficiency.mark('cssEnd');
  efficiency.measure('cssTime', 'cssStart', 'cssEnd');
</script>

Right here, we drop a high-resolution timestamp — cssStart — utilizing efficiency.mark().
We then fetch a synchronous stylesheet, app.css, earlier than dropping a second
high-resolution timestamp, cssEnd, utilizing efficiency.mark() as soon as extra.
Lastly, we use efficiency.measure() to create a measure of the period of
the delta between cssStart and cssEnd.

We may log any of the above .mark()s or .measure()s to the console. For
instance, to get the beginning time of cssStart, we may do:

console.log(`CSS Begin: ${efficiency.getEntriesByName('cssStart')[0].startTime} ms`);

Or the period of the cssTime measure:

console.log(`CSS Length: ${efficiency.getEntriesByName('cssTime')[0].period} ms`);

Word that .mark()’s helpful property is startTime and .measures()’s is
period.

You should utilize supply:console-api to scope your Console
messages solely to issues logged to it. A lot cleaner.

We will use efficiency.mark() and .measure() in JavaScript, too, naturally:

efficiency.mark('jsStart');

// Simulate costly JavaScript execution
setTimeout(() => {
  efficiency.mark('jsEnd');
  efficiency.measure('jsTime', 'jsStart', 'jsEnd');

  console.log(efficiency.getEntriesByName('jsStart')[0].startTime);
  console.log(efficiency.getEntriesByName('jsTime')[0].period);
}, 1000);

Right here we’re simulating an costly little bit of scripting that we’d need to
instrument and optimise.

These are neat, however the significantly good factor about them is that Chrome
DevTools will robotically decide up these marks and measures, and show them
within the Timings monitor of the Efficiency panel:

Chrome Performance panel showing User Timing entries cssTime, jsTime, and jsEnd added via performance.mark() and .measure().
Word that cssTime and jsTime take up
a proportional quantity of house to their period, however jsEnd,
a .mark(), takes up a skinny sliver of the UI because it represents
a second in time. .mark()s are discovered above
.measure()s.

The good thing about the console.log() method is that it’s a lot quicker — you don’t
have to run a full efficiency profile, however the good thing about the Efficiency panel
technique is that you would be able to visualise the instances in context of your utility’s
runtime. The previous is nice when you simply want the quantity as shortly as attainable;
the latter is nice when you’re making an attempt to contextualise your work.

Truthfully, when you’ve by no means seen that earlier than, I dare say this text has supplied
a bunch of worth already! Subsequent, go and see put this into use with my
Measure What You Influence, Not What You
Affect

article which supplies good use-cases and examples for utilizing these bare-metal
metrics.

The Extensibility API

The brand new Extensibility API permits us to increase this performance. We will create
arbitrary customized tracks within the Efficiency panel, not limiting us to solely the
default Timings monitor, and we will add our personal metadata to those marks and
measures that can be utilized to floor extra info within the DevTools UI!

So as to take action, we have to write fairly much more code than the
efficiency.mark() and .measure()s we’ve simply checked out. We start by
extending the .mark() or .measure() with a devtools object that lives in
the particulars property, The entire level of this publish is to chop by means of the fluff
and present you, pragmatically, precisely what you do and don’t want.

Minimal Viable Measurement

Earlier than we will do something, within the Efficiency panel’s settings, we have to
allow Present customized tracks:

Settings panel in Chrome DevTools with the ‘Show custom tracks’ option enabled for using the Performance Extensibility API.
Look within the Efficiency panel’s settings, not DevTools’ total
settings.

On this part, I’ll present you the naked minimal it’s essential make a begin with
the Extensibility API. Some features are obligatory and others, like colors, are
totally non-compulsory.

Beginning with .mark(), the dataType is required; nothing else is. Let’s
convert our jsEnd .mark() to make use of the Extensibility API:

efficiency.mark('jsEnd', {
  element: {
    devtools: {
      dataType: 'marker'
    }
  }
});

We’re forgoing the rest for now, however this is step one to adopting the
Extensibility API for efficiency.mark():

DevTools Performance panel showing a custom marker jsEnd added using the Extensibility API and styled with a custom colour.
Look towards the top-right and notice the sunshine blue
jsEnd marker. That’s the prolonged
efficiency.mark() in motion.

Key enhancements:

  1. The marker is very obvious! It’s like a giant flag which makes recognizing
    .mark()s infinitely simpler.
  2. The marker has additionally positioned a dotted line all the best way down subsequent
    tracks, together with the Foremost thread.

Nonetheless, there are two main downsides to date:

  1. The marker is as large because the textual content it incorporates — this will make issues
    a bit of deceptive as markers now now not look like a time limit,
    however probably a period. When you get used to this, you get used to it,
    however at first, it’s simple to mistake a .mark() for a .meaasure().
  2. There’s completely no means of figuring out at what time the .mark() was
    fired!
    Even clicking the marker itself doesn’t present us any timestamp
    info. Neither hovering or clicking the marker provides us the excessive
    decision timing that we’d use a .mark() for within the first place:

Chrome DevTools Summary pane missing timestamp details for a custom performance.mark() entry using the Extensibility API.
The UI doesn’t floor any timestamp info anyplace. I discover
this gorgeous weird.

To this finish, I’d be inclined to make use of .mark() much less as a timestamp and extra as a,
effectively, marker — it could shortly convey your consideration to the related a part of your
hint.

That’s your minimal viable .mark().

efficiency.measure() is a bit more helpful, although. Let’s convert cssTime
to its minimal viable model:

efficiency.measure('cssTime', {
  begin: 'cssStart',
  finish: 'cssEnd',
  element: {
    devtools: {
      monitor: 'CSS'
    }
  }
});

We nonetheless have to cross within the reference begin .mark() through the begin:
property. Our finish marker, if omitted, defaults to proper now — when the
.measure() is being known as — or could be supplied explicitly through finish:. The
monitor property is obligatory, and this varieties our minimal viable .measure().
Word that we don’t want to provide the dataType property as its omission
defaults to dataType: 'track-entry', which is precisely what we’d like. Let’s see
what this appears like.

Hey! That’s fairly neat!

Custom track labelled ‘CSS’ in Chrome DevTools Performance panel created using performance.measure() and the Extensibility API.

We now have our first customized monitor titled CSS, sourced from our monitor:
'CSS'
. That is the least we have to do to be able to make use of the
Extensibility API for efficiency.measure(). Subsequent, we’ll take it additional.

Maximising the Extensibility API

What I simply confirmed you was the naked minimal to rise up and operating with the
Extensibility API. .mark() is a bit of underwhelming, for my part, however the
means we will lengthen .measure() may be very cool. Let’s begin with the built-in
extensions we’ve.

Tracks and Colors

With each .mark() and .measure(), we will apply customized colors. Not arbitrary
or totally customized, like #f43059, however from DevTools’ personal palette: major,
primary-light, primary-dark, secondary, secondary-light,
secondary-dark, tertiary, tertiary-light, tertiary-dark, and error.

Let’s lengthen our .mark() from earlier than a bit of additional:

efficiency.mark('jsEnd', {
  element: {
    devtools: {
      dataType: 'marker',
      shade: 'secondary-dark'
    }
  }
});

Discover that our jsEnd marker is now a darkish pinky-purple:

Marker text in the Performance panel replaced with tooltipText using the Extensibility API — note the absence of an actual tooltip.
The highest-right marker is now darkish pink, which I assume maps to secondary-dark.

Simple sufficient! Subsequent, let’s add some extra descriptive tooltip textual content:

efficiency.mark('jsEnd', {
  element: {
    devtools: {
      dataType: 'marker',
      shade: 'secondary-dark',
      tooltipText: 'Simulated JS Execution Full'
    }
  }
});

To be sincere, that is no higher, and definitely no extra handy, than simply
utilizing a unique string instead of jsEnd — this textual content hasn’t produced
a tooltip, however reasonably simply changed the marker’s textual content.

The takeaway up to now is that the Extensibility API is much less helpful for
efficiency.mark().

Chrome DevTools Summary pane displaying custom metadata properties attached via the Extensibility API’s properties array.
The tooltipText merely replaces the marker’s textual content and
doesn’t really create a tooltip.

Lastly, for .mark(), we will cross in arbitrary metadata. That may very well be fairly
helpful for different builders choosing up a venture:

efficiency.mark('jsEnd', {
  element: {
    devtools: {
      dataType: 'marker',
      shade: 'secondary-dark',
      tooltipText: 'Simulated JS Execution Full',
      properties: [
        ['File', 'app.js'],
        ['Function', 'setTimeout()']
      ]
    }
  }
});

Above, I’ve handed in almost-pointless knowledge as an instance the purpose, however I’m
positive you’ll be able to consider your individual helpful use-cases.

Custom .measure() entry with tooltip, colour, and rich metadata shown in a dedicated CSS track using the Extensibility API.
Word the customized knowledge that now seems within the Abstract pane.

All the options I simply confirmed you (shade, tooltipText, and properties)
apply equally to efficiency.measure(), so let’s leap forward and produce our
efficiency.measure() instance updated in a single go:

efficiency.measure('cssTime', {
  begin: 'cssStart',
  finish: 'cssEnd',
  element: {
    devtools: {
      monitor: 'CSS',
      shade: 'secondary-dark',
      tooltipText: 'Exterior CSS fetched and parsed',
      properties: [
        ['URL', app.css],
        ['Transferred Size', 29.3 KB],
        ['Decoded Body Size', 311.8 KB],
        ['Queuing & Latency', 104 ms],
        ['Download', 380 ms]
      ]
    }
  }
});

I’ve added a shade, a tooltipText, and a few made up metadata in
properties. Word that I really constructed a demo that used the Useful resource Timing
API to seize these numbers for actual. That code is in the appendix.

Chrome Performance panel with grouped custom tracks for CSS and JS under ‘First Party’, showing cssTime and jsTime entries with full metadata.
The .measure() really will get a correct tooltip, and we
have wealthy metadata within the Abstract pane.

Now that is extra prefer it!

  1. We nonetheless have our devoted CSS monitor;
  2. The tooltipText really appears and acts like a tooltip;
  3. The Abstract pane has a number of good, wealthy metadata!

That is the place I see the Extensibility API changing into significantly helpful. There’s
only one thing more I need to present you: monitor teams.

Observe Teams

We created a customized CSS monitor utilizing monitor: 'CSS'. We would need to make
a monitor for JS, API calls, you identify it. We will then take all of those tracks and
group them right into a monitor group.

Observe teams are helpful if, say, we need to monitor first- and third-party
attribution individually, or if our codebase has totally different groups who need to
isolate their instrumentation from one another. They’re additionally extremely simple to
arrange. Let’s evolve our .measure() a bit of extra:

efficiency.measure('cssTime', {
  begin: 'cssStart',
  finish: 'cssEnd',
  element: {
    devtools: {
      monitor: 'CSS',
      trackGroup: 'First Social gathering',
      shade: 'secondary-dark',
      tooltipText: 'Exterior CSS fetched and parsed',
      properties: [
        ['URL', app.css],
        ['Transferred Size', 29.3 KB],
        ['Decoded Body Size', 311.8 KB],
        ['Queuing & Latency', 104 ms],
        ['Download', 380 ms]
      ]
    }
  }
});

And let’s shortly return and add trackGroup: 'First Social gathering' to our JS’s
.measure():

efficiency.measure('jsTime', {
  begin: 'jsStart',
  finish: 'jsEnd',
  element: {
    devtools: {
      monitor: 'JS',
      trackGroup: 'First Social gathering',
      shade: 'secondary-dark',
      tooltipText: 'Simulated JS Execution Full',
      properties: [
        ['File', 'app.js'],
        ['Function', 'setTimeout()']
      ]
    }
  }
});

…and what will we get?

Each our CSS and JS tracks are actually nested beneath
a First Social gathering monitor group.

Now we’ve a monitor group known as First Social gathering which incorporates each a CSS and
a JS sub-track!

I hope you’ll be able to already start to think about and envision use-cases for tracks and
monitor teams. Should you’re profiling and instrumenting your utility with
efficiency.mark() and efficiency.measure() already, the concept of getting it
all organised absolutely excites you!

Recap

The syntax for all of that is very repetetive and cumbersome, so all I might say
is begin with as little as you will get away with. Personally, I might not
suggest utilizing the Extensibility API for efficiency.mark(), so I’m not going
to confuse folks by recapping it.

For efficiency.measure(), all you really want to get off the bottom is:

efficiency.measure('<identify>', {
  begin: '<begin>',
  finish: '<finish>',
  element: {
    devtools: {
      monitor: '<track-name>'
    }
  }
});

This can robotically transfer this measure into its personal customized monitor named, in
this case, <track-name>.

Subsequent up, I’d counsel trying into monitor teams so that you could higher organise
your self:

efficiency.measure('<identify>', {
  begin: '<begin>',
  finish: '<finish>',
  element: {
    devtools: {
      monitor: '<track-name>',
      trackGroup: '<group-name>'
    }
  }
});

Maybe a bunch for any code that comes out of your design system or your individual
first social gathering utility, with sub-tracks for JS, API calls, and many others. It truly is up
to you.

Past that, we’re principally fascinated about including metadata and customized colors, however
don’t fear about that till you’ve bought the mechanism dialled in.

Third Events

Should you work on a framework or a 3rd social gathering that devices its personal Person
Timings, please contemplate shifting them into your individual monitor group. It might be good
to see, for instance, Subsequent.js route-change or hydration timings in their very own
place.

Appendix

Useful resource Timing API Instance

Drop this straight into an HTML file, hearth it up in Chrome, and it’ll Simply
Work™.

<!doctype html>
<html lang=en-gb>
  <meta charset=utf-8>
  <meta identify=viewport content material="width=device-width, minimum-scale=1.0">

  <title>Extensibility API</title>

  <script>
    efficiency.mark('cssStart', {
      element: {
        devtools: {
          dataType: "marker",
          tooltipText: 'Get Bootstrap CSS from CDN',
          shade: "secondary-light"
        }
      }
    });
  </script>

  <hyperlink rel=stylesheet href=https://cdn.jsdelivr.internet/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css id=jsCSS>

  <script>

    efficiency.mark('cssEnd');

    // Seize stylesheet’s timing metadata.
    const css                  = doc.getElementById('jsCSS');
    const cssURL               = css.href;
    const cssTimingInformation = efficiency.getEntriesByName(cssURL)[0];
    const cssTransferSize      = (cssTimingInformation.transferSize    / 1024).toFixed(2);
    const cssDecodedBodySize   = (cssTimingInformation.decodedBodySize / 1024).toFixed(2);
    const cssLatencyDuration   = (cssTimingInformation.responseStart   - cssTimingInformation.startTime).toFixed(2);
    const cssdownloadDuration  = (cssTimingInformation.responseEnd     - cssTimingInformation.responseStart).toFixed(2);

  </script>

  <script>

    efficiency.measure('cssTime', {
      begin: 'cssStart',
      finish:   'cssEnd',
      element: {
        devtools: {
          dataType:    'track-entry',
          trackGroup:  'Third Social gathering Instrumentation',
          monitor:       'CSS',
          tooltipText: 'CSS Downloaded and Parsed',
          shade:       'secondary-light',
          properties: [
            ['URL',                  cssURL],
            ['Transferred Size',  `${cssTransferSize} KB`],
            ['Decoded Body Size', `${cssDecodedBodySize} KB`],
            ['Queuing & Latency', `${cssLatencyDuration} ms`],
            ['Download',          `${cssdownloadDuration} ms`]
          ]
        }
      }
    });

  </script>

This Internet Efficiency publish is tagged with:

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments