Style profiler preview

CSS selector matching is often neglected when it comes to performance of web documents and applications. For small documents, the performance impact is negligible, but for documents with a large DOM (like the Opera Dragonfly application itself), a single "bad" selector can have a serious impact.

CSS selector matching refers to the process where a browser tries to match a selector against an element in the DOM. In terms of performance, some selectors are better than others. For instance, an ID selector is better than the universal selector (*), because the former only matches one element (and is cached). Matching elements in a big DOM against many unspecific selectors might cause your page to render significantly slower because of the number of elements affected.

We recently introduced support for style profiling in Core, and this is the first preview of its implementation in Opera Dragonfly.

Opera takes several actions from the time it loads a document to when it is rendered on screen: markup, stylesheets and scripts are parsed, scripts are executed, parts of the page are painted on screen. All of these events that occur while rendering are presented in a timeline in this profiler. Our focus has been on providing detailed information about CSS selectors. Clicking the "Style recalculation" header, or one of the individual style recalculation events in the timeline, will give you a list of the most expensive selectors.

Note: This is a special build of Opera Dragonfly – the functionality has not yet been merged with either the experimental or cutting-edge builds. Only the Profiler tab is available. To test, grab a recent Opera build (11.60 or 12) from the Desktop team blog, and set the Developer Tools URL to:

https://dragonfly.opera.com/app/profiler/

Keep in my mind that this is an early preview. Lots of things will be tweaked before this is released.

As a real-world example of how big the impact can be on performance, I made a test with the full HTML5 specification downloaded locally and ran the profiler. I noticed a few of the most expensive selectors had ":link" and ":visited". I changed these to instead be "a:link" or "a:visited" (in this case they were equivalent in terms of which elements matched). This trivial change makes the engine use a cache, and brought the selector matching time down from about 14 seconds to about 11 seconds.

Apart from detailed selector matching performance, you can hover on events in the timeline to get more information about them. For example, when you hover on a paint event, it will show the point in the viewport where the paint event occurred, and how big the painted area was.

This is only the first part of a Dragonfly profiler. A JavaScript profiler is on the roadmap, so keep your eyes open.

CSS shorthands!What's New in Opera Dragonfly with Opera Next

Comments

Dustin WilsonKhadgar Wednesday, November 30, 2011 4:29:49 PM

Whoa.

Patrick H. Laukepatrickhlauke Wednesday, November 30, 2011 4:59:47 PM

Awesome stuff. Nice to finally see this unleashed smile

Martin KadlecBS-Harou Wednesday, November 30, 2011 5:25:28 PM

Cool, going to test smile

SteveKong Wednesday, November 30, 2011 5:44:12 PM

Impressive.

exterminans Wednesday, November 30, 2011 6:00:51 PM

Impressive indeed.

Александр Карпинскийhomm Wednesday, November 30, 2011 6:01:53 PM

What mean «hits» in third column?

Pablo MendozaPabloMendoza Wednesday, November 30, 2011 6:07:34 PM

Thanks! now I can see all the reflows in my web whistle

BLOBO Wednesday, November 30, 2011 7:46:15 PM

nice one i like it !

Constantine Vesnac69 Wednesday, November 30, 2011 8:01:47 PM

Awesome! wizard Of course it crashed, of course ui is not good yet, but looks very promising.

Two questions, though,
- what does Thread evaluation means? It shows very high numbers (or not ?!) on many sites.

- when Event details are expected to become available ?

Christian Krebsaleto Wednesday, November 30, 2011 9:53:30 PM

Originally posted by Александр Карпинский:

What mean «hits» in third column?


That is how often the selector was checked. In a reflow each selector needs to be checked against each invalidated element.

Originally posted by Constantine Vesna:

- what does Thread evaluation means? It shows very high numbers (or not ?!) on many sites.


That is any JavaScript thread running during profiling. It will be expandable in the future, similar to Style recalculation, to show detailed informations about that thread.

LLleonardolaporte Thursday, December 1, 2011 5:02:05 AM

Dragonfly is growing. need to feed it. smile

grafio Thursday, December 1, 2011 9:19:52 AM

Very nice.

Sam Duttonsamdutton Thursday, December 1, 2011 10:07:27 AM

Very useful -- thank you.

Would love to see the items be clickable, to view the matched (or first matched) element in the DOM.

IllusionMH109th Thursday, December 1, 2011 12:23:42 PM

Wow!
It will be useful:) Waiting for full implementation in DF

Is there a way(at this time) to start recording automatically with page reload?

Patrick O'Reillypaddy2k Thursday, December 1, 2011 1:54:16 PM

Excellent tool. It helped me speed up a very heavy page in IE6 by highlighting the inefficiencies.

Unregistered user Tuesday, December 6, 2011 6:28:15 AM

kangax writes: Tried this today. Looks like a great start. Few wanted features, after working with profiler for a bit: - Start automatically on page load (for more precise repeated tests) - Rule search/filter (just a search box, to find where exactly certain rule is, and how performant it is after you changed it to be more specific) - Ability to jump to css declaration in stylesheet/style element from corresponding rule in the list in profiler - Ability to "see" (highlight?) all matching elements for a given rul in the list in profiler

David Håsätherhzr Tuesday, December 6, 2011 12:27:00 PM

Thanks for the feedback kangax and others, will take this into consideration for the final version.

Unregistered user Tuesday, December 6, 2011 6:15:57 PM

Thierry writes: That's all I asked for Christmas! :)

Unregistered user Tuesday, December 6, 2011 6:25:01 PM

Sumeet Chawla writes: Looks like a game changer! Awesome stuff!

Unregistered user Tuesday, December 6, 2011 6:51:25 PM

Fábio Miranda Costa writes: Could you please explain better the following: "This trivial change makes the engine use a cache, and brought the selector matching time down from about 14 seconds to about 11 seconds." It used to take 14 seconds to match? I mean, it's kind of a big number... It's 14ms right?

David Håsätherhzr Wednesday, December 7, 2011 10:18:44 AM

Fábio Miranda Costa, 14 seconds is accurate. It's for all selectors and for the whole document (the HTML5 spec is huge).

Unregistered user Thursday, December 8, 2011 10:46:52 PM

Jaime writes: good to know. Thanks opera

DillonAstrophizz Saturday, December 10, 2011 1:58:07 AM

According to https://bugs.webkit.org/show_bug.cgi?id=74004#c12 Webkit only needs ~1/2 a second to match selectors in the HTML5 specification. My own observation seems to confirm that Opera takes significantly longer worried

David Håsätherhzr Saturday, December 10, 2011 2:00:36 PM

Originally posted by Astrophizz:

According to https://bugs.webkit.org/show_bug.cgi?id=74004#c12 Webkit only needs ~1/2 a second to match selectors in the HTML5 specification. My own observation seems to confirm that Opera takes significantly longer worried

It depends on hardware too of course (the machine I used to benchmark is quite slow), but selector matching in WebKit has been optimized a lot recently (by the very author of that comment).

Unregistered user Thursday, December 15, 2011 10:33:40 PM

kangax writes: Another suggestion: show time in ms for each row, not only in %. You can already see it when hovering over first cell now, but when you're optimizing something, you don't want to hover over all cells, to see where exactly improvement happened (and how significant it is). Finally, total time in ms (for layout, paint, style recalc, etc. combined) would be great addition as well.

Unregistered user Friday, December 16, 2011 12:26:06 AM

kangax writes: There seem to be some glitches with multiple tabs. Profiler sometimes behaves as if I'm profiling not the tab that I'm currently in, but the other one (previously profiled?).

David Håsätherhzr Friday, December 16, 2011 12:37:32 PM

Will look into these things, kangax. If you have more information about the multiple-tabs issue, please post them here. Thanks.

Constantine Vesnac69 Saturday, December 17, 2011 4:29:42 PM

Sometimes it does not profile anything at all. (or maybe it profiles something hidden) As it shows NO painting or layout events at all. Only JS.

Closing and reopening Dragonfy helps.

kangax Monday, December 19, 2011 9:49:53 PM

Noticed another issue: I get "Profiling failed" once in a while and can't figure out what exactly causes it. I just open a new tab (which shows speed dial window), start profiler, then Cmd+L to address bar, insert url, press enter, and once site loads, stop profiler — to see what's going on during page load. And "Profiling failed" pops up once in a while.

Unregistered user Thursday, January 5, 2012 1:03:17 PM

Dave writes: This is really great. I've just been playing around with it on a site I'd made and noticed something which may be a bug or it might be working as intended and I've just misunderstood the 'hits' column. In my app I'm including a CSS file that is only used on a certain page. I know, I know, this is inefficient so I'll look to change it, but I noticed that those selectors are showing as having been hit even though nothing on the current page should use them. For example, it shows: .PayslipTable td - 35 hits .ContentsTable td - 35 hits .DashboardTable td - 35 hits As all having, for example, 35 hits, even though only the DashboardTable is in the markup for the current page. Is that because it hit 35 td's and thus had to query all of those selectors (despite 2 of them not being relevant due to the class), or should it show: .PayslipTable td - 0 hits .ContentsTable td - 0 hits .DashboardTable td - 35 hits Like I say, it might be correct and just not showing what I originally (mistakenly) expected!

Unregistered user Thursday, January 5, 2012 1:04:22 PM

Dave writes: Ouch, sorry - lost all my formatting there. Turns out that line breaks are also removed from Anonymous comments!

David Håsätherhzr Friday, January 6, 2012 2:08:21 PM

Dave, yes, that's correct. Remember that selectors are evaluated from right to left. The engine starts at "td", then checks if an ancestor has the class.

Write a comment

New comments have been disabled for this post.