Re: [csswg-drafts] [css-highlight-api][css-contain] static ranges and css-contain (#4598)

> The intent is to save the browser the work of doing style, layout, paint and compositing work in that subtree

Actually, the intent is pretty much the exact opposite: the intent is to make sure that any work the Browser has to do is limited to that subtree, and saving from having to do work elsewhere.

Here's another example, more realistic since unlike the previous one, it could have performance implications.

Say you have a website tracking stock tickers, each represented by some card. You're tracking the whole stock market, so you have lots of cards (a few thousands), and since they're so many, most of them are offscren. Also, they frequently update (possibly several times per second for highly traded stock), because you're following the market in real time.

You set `contain:strict` on each card, to make sure that updating one card doesn't cause the browser to need to reevaluate anything else (and so that if that particular card is off-screen, it doesn't need to relayout/repaint anything at all).

On top of that, let's say you implement some kind of custom find-in-page (maybe with regexp support?) using custom highlights. If the user searches for something common (e.g. `\s+\d+\s+`), you might have a lot of ranges on your page. Live-ranges are not appropriate: each time the DOM updates and changes the text in some card, you don't want the UA to update the start/end points of the range to the nearest valid offset, since that may not match the searched pattern. When  the DOM changes, your script handles trashing and/creating ranges as appropriate. Maybe it throttles these updates and only does them every 100ms rather than on every change, to avoid busy work. Letting the browser adjust the ranges before deleting and recreating them would just be a waste of time.

Now, if the UA simply allows highlights backed by static ranges to cross containment boundaries and be painted as long as they're valid, then, every time the DOM in a card is updated, you need to:
* find all the ranges that previously has at least one end in the updated card and check if it's still valid, even if the card is offscreen (because part of the range might be on-screen)
* For any that did become invalid, you need to repaint parts of the document that were outside of the contained area if they were covered and affected by that no-longer-valid range, even if the updated card is offscreen
* Right after you do that, the author's script will likely trash that range that you just did some work for, and possibly recreate a new one (if it found a new match for the user's search), which possibly will cause you to need to repaint again, and as that too could be over the whole document.

So, potentially, you're calling for evaluation of range validity, and potential repaints of the whole document many thousands of time per second. :(

Instead, if highlights backed by static ranges never paint when a range crosses a containment boundary, this whole thing gets short-circuited most of the time. The first step is to check whether the updated card is off-screen, and if so, you can just stop there. No need to check for any range's validity. No need to repaint anything at all. If it is on screen, you just need to repaint that particular card (and skip now-invalid ranges while doing that) and nothing else.

Now, admittedly, if you did intent to let the user find things that span across containment boundaries, then that's unfortunate, because that speed-up is achieved by making that impossible. Maybe authors just need to be aware of that, and only use static ranges either when they're not using containment know that they don't need to cross containment boundaries, and use live ranges when that's not an option. That doesn't sound author friendly though.

> This seems similar to the effect of using regular browser highlighting with a mouse gesture to cover a contain:paint subtree plus other content, then scrolling the subtree off-screen and subsequently performing a mutation to remove the endpoint of the highlight.

This is not similar, because that range is a live one.

* You need to update its end point anyway when you mutate the DOM. Using static ranges is exactly intended to let you opt out of that, so if static ranges need re-validation when the DOM changes, the benefit of using static ranges goes away
* A mutation within a contained subtree may move the end-point of a live-range that was within that subtree. If that subtree is on screen, it will need to be repainted (it had to anyway, since the DOM has changed), but as that moving end-point cannot be moved to outside of the contained subtree by a DOM change within the subtree, the part of the range that is outside of the contained area cannot be changed by this operation, and doesn't thus cannot trigger a repaint of a broader part of the document.

-- 
GitHub Notification of comment by frivoal
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/4598#issuecomment-994523422 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 15 December 2021 08:58:45 UTC