Open Bug 1839469 Opened 2 years ago Updated 8 months ago

'Bad Apple' CSS Custom Highlight demo is slower in Firefox than Chromium

Categories

(Core :: CSS Parsing and Computation, defect)

Firefox 116
x86_64
Linux
defect

Tracking

()

Tracking Status
firefox116 --- affected

People

(Reporter: gregp, Unassigned)

References

(Blocks 1 open bug, )

Details

Steps to reproduce:

  1. Navigate to about:config
  2. Set dom.customHighlightAPI.enabled to true
  3. Navigate to https://bucket.daz.cat/work/igalia/0/highlightroll.blinkon.html
  4. Press play

Actual results:
Jank

Expected results:
Less jank

https://share.firefox.dev/3CDcPJn

There is fps in the title of the page. Chrome gets to 16fps at some point where Nightly is around 10fps.
The profile nicely points to the exact thing being slow. It is mostly mozilla::dom::Selection::StyledRanges::FindInsertionPoint
nsTextPaintStyle::GetCustomHighlightColors also shows up quite a bit.

Yeah, it looks like nsTextFrame queries the selection details quite often (nsTextFrame::GetSelectionDetails()), like in every frame or so (?). I wonder if it would be feasible of caching the selection details for as long as there are no DOM mutations?

I would guess the same behaviour could be reproduced by using find on a page with many results. So this showing up for custom highlight may just be a symptom of a more general issue.

The severity field is not set for this bug.
:dholbert, could you have a look please?

For more information, please visit BugBot documentation.

Flags: needinfo?(dholbert)
Severity: -- → S3
Flags: needinfo?(dholbert)

Seems to still reproduce. Here's a more recent profile: https://share.firefox.dev/3wBMcFn

For whatever reason, the archive.org link doesn't play in Chrome (v126 dev) for me. Clicking on the "play" button has no effect aside from a Web Console error message: 3highlightroll.blinkon.html:61 Uncaught (in promise) DOMException: The element has no supported sources. That seems to be because https://web.archive.org/web/20230620053423id_/https://bucket.daz.cat/work/igalia/0/highlightroll96.webm doesn't fully load there for some reason. The original bucket.daz.cat/ URL still seems to be up, though, and it still works in Chrome.

Anyway: nsTextFrame::GetSelectionDetails still seems to be the hot path here.

The demo itself seems to be doing the following:

  • it generates 864 spans (or "chunks", with id chunk0 through chunk863) that each contain 8 space characters (U+3000). Each space is effectively a "pixel", 6912 individual pixels total.

The demo addresses these pixels to dynamically paint them by doing the following work up-front:

  • it creates an array of 8 Highlights.
  • for each of our 864 spans, it generates a range for each of the 8 space characters, and it inserts each range (single-character) ranges into the corresponding Hightlight.
  • it generates a separate CSS rule to target each highlight-type within each of the 864 spans. So each of the 6912 "pixels" (each space character) gets its own dedicated CSS rule, looking something like this one for the space character at (0-based) index #2 in the (0-based) 486th span:
#chunk486::highlight(x2) {
  background: rgb(2, 0, 2);
}

Then the demo animates the colors of these "pixels" as follows:

  • It's got a video that it plays in the background
  • on each requestAnimationFrame tick, we go through every single CSS rule like the one I quoted above and update the background to match the corresponding pixel in the video.

So: during the animation, the DOM and the ranges are all static, and it's only the colors in the CSS rules that are dynamically changing (like so, simplified):

      const sheet = document.styleSheets[1];
      const rule = sheet.cssRules[i];
      rule.style.backgroundColor = `#${r_}${g_}${b_}`;   // (r_, g_, and b_ are representing hex color-channel values)

So that means the idea in comment 2 should definitely help here (caching the selection details for as long as there are no DOM mutations).

You need to log in before you can comment on or make changes to this bug.