Participants

Admin

Element timing for containers - continued discussion

Recording

Jason: Discussed this back in December

.. Will recap the discussion, present the polyfill and continue discussion

… Talked about how Element Timing only supports a small subset of elements

… More of the web is component based, people want to know when a component or a subsection of the DOM was painted

… Even composite elements have this problem and are not candidates for Element Timing

… Extends into LCP.

… want to be able to measure components as well

… Decided to try out what a user-land prototype may look like

https://jasonwilliams.github.io/container-timing/

… WIP polyfill

… Will identify elementtiming attribute on elements, check which of them are “container roots”

… Then it’d attach elementtiming attributes on all of their children and wait for perfobserver

… Replaces the prefobserver with this class TODO

… Changes that happen inside the container fire a perf entry for the container

… The entry interface is similar to a normal element timing (differences highlighted)

… startTime is the first paint event inside the container

… renderTime is the latest paint event

… lastElementSubElement - the last element

… open question - should we include size? LCP does, but including this would require getBoundingClientRect, which will trigger style layout and slowness

… In the table example, once the container is painted we get an entry, and on update we get another entry

… startTime didn’t change, the lastPaintedSubElement did

… For a single paint, we probably have many sub elements that painted at the same time

… Another example of adding a paragraph into the DOM

… Works because the polyfill is using mutation observer and we add the elementtiming attribute to the new element immediately

… So can attribute back the element when we get the performance entry

… Shadow DOM …interesting. The polyfill doesn’t work because we can’t get events from inside the shadow root

… Getting a single event for the inside of the shadow root, I guess it’s treated as a single element

… Finally SVG, similar to shadow DOM. No hooks to know when an SVG finished painting. Any solution here would need to be provided by the browser

… we can argue if SVG is a single element or multiple element in cases of progressive rendering inside the SVG

… Element Timing is binary. Container timing would emit entries multiple times, and would fire events after interaction, etc.

… e.g. a carousel would trigger element for each image that was injected.

… Not relevant if we’re focused

… TODO

… Polyfill hasn’t touched on animations at all, not sure if it can pick up on that (not sure of feasibility)

… Showing the last sub-painted element, is that enough?

… e.g. if element has content painted in it and container element that it fires, but only a small section painted, does the developer know how much is enough to say this container is ready?

Michal: I wasn’t sure, but was glad to see that MutaitonObservers are viable to inject elementTiming attribute for content about to be painted

Jase: Happily surprised to see that work

Yoav: Would that be race-y?

… I would expect because MO fire async

Michal: Or are they aligned with animation frames?

… I think text would be presented in the very next frame

… Since it worked with text, I think it should work

Jase: Is there a good way for testing this out, or a testing-bed where we can be absolutely certain

Yoav: Very slow machines, or introducing a delay explicitly

… Observing code when MO fires or is dispatched

Michael: Anyone know guaranteed timing of MO?

… Or you can use UserTiming and see where it’s shown related to rendering

Noam: MO are batched into the same microtask and presented

… Less eager than MutationEvents but more eager than rAF

Yoav: Mutation Events are going away

Michal: Generally, super-thrilled you could put together a polyfill and demo.  Type of feedback I’d hope to see is what is polyfill-able and not?

… Then see what are the value?

… First question is it seems like you have to inject polyfill eagerly in initial content embedded into the page has to have elementTiming attribute in the page of HTML

… Already a law of existing ElementTiming

… Any library that tries to lazyLoad itself (or late) cannot sprinkle page with ElementTiming, if I understand correctly and this would apply here

Jase: Yes you need to inject eagerly

… polyfill starts marking markup right away

… It looks like it’s fine working before .observe() is called

… Feels like as long as everything is in place before .observe() is OK, but not sure if anything earlier is needed

Yoav: I suspect that is not necessarily true, with buffered:true

Michal: But generally you have to have the elementTiming attribute before the first paint of a node

… No way even to know if the thing you’re applying the ET tag to won’t paint due to X Y Z

… From the server you’d have to apply elementTiming tag to all children immediately

Jase: In polyfill we’re blocking in the head and injecting those

… For regular ET you’d have to have those annotated anyway

Michal: If ET could be a bit more flexible here, polyfill could be loaded a bit lazier

Ian: Wondering if there’s any caveats with polyfill or in general on nested containers

… Time container you’re adding to another container you’re timing, does it fire events on both (or should it?)

Jase: I was thinking about this, I haven’t taken nested containers into account. Polyfill works is if element has ET on it, it will search for nearest parent container

… For instance if you had two containers, and inner had a paint event, the outer would not currently emit and entry, only the inner container

… How would we expect it to behave?

… Not too much work or discussion on how we want nested containers to work

Ian: OK so still an open question

… Imagine different authors on different parts of a site may want to use this

… Another question, want to give developers an option for how much of a container was painted

... Many containers expand to fill contents, so it’s 100%

… Working with something else or containers with fixed sizes?

Jase: Containers can expand to fill whatever is injected, more on the fixed container side, text and an image

… Fixed widget, whether image is there or not, it doesn’t change size

… If image takes up more size, do they want to know if image and the whole container loaded or just the text

… Geared more towards fixed-sized widgets

… Added a lastXelement so developers can check

Noam: Regarding question from slide 14, it feels to me that the answer is “Yes”, we should allow developers some way to indicate whent hey’re interested in getting events from the container

… I can imagine when this is important, to stop and modify things or not get events

… Not sure what form API should take

Michal: observer.disconnect() exists

Noam: Maybe a timeout on .observe() options

Yoav: I think this is different from .disconnect()

Noam: For a certain container, a dialog, maybe hidden

Yoav: .disconnect() will disconnect observer but other observers will still get timing

… You want to remove elementTiming attribute and have that stop emitting entries

Noam: So top element container .removeAttribute() would recursively remove it from all child elements

Yoav: Or in polyfill it can remove all timings from all children and stop adding it to new additions

Noam: Second question, have you spent time thinking about the performance impact of adding attributes and traversing elements

… What could we expect to be the performance impact of such behavior?

Jase: Examples you saw, I played around with having it on and off, but didn’t feel like a real-world scenario

… Follow-up for me

Yoav: On easy way to test worst-case scenario of ElementTiming is to remove in Chromium the check that would report ET for everything, to see if that regresses something

… At the very least I’d add that behind a flag and flip it in a WPT and see it on a bunch of popular sites to see if there’s any visible impact to this or not

… Take it from there if the answer is “Yes”

… Maybe a broader scale experiment could show

Noam: Even if it doesn’t show on local benchmark, likely to show on wider-scale higher-percentiles

Yoav: Regarding Shadow DOM, we have an open issue for the longest while

https://github.com/WICG/element-timing/issues/3

… Discussed at TPAC

… If ElementTiming would’ve reported from inside open Shadow DOMs, would that have been enough for polyfill to take that into account

… If we fix ElementTiming on that front, is it enough for polyfill to take over

Jase: How do you envision ET added to the open Shadow DOM host, getting the event like everything else?

Yoav: ET being added as part of the component, various parts in Shadow DOM, internal elements getting events fired

… May be over-simplifying this

Jase: Would allow PerformanceObserver outside to pick up on these events?  Then the polyfill should work

Michal: Does anyone have context for why ET is not supported in Shadow DOM?
Yoav: For initial release of ET we didn’t want to tackle complexity

… Main reason was it was too complex

… People moved on

… I think if we concentrated effort on solving it, we could reach some consensus

(TPAC discussion links https://docs.google.com/document/d/1RbszCu4NG-fcRRoL1TsP6SvjohIuz-uxv5NZm_6iA4U/edit#heading=h.3zh1jt8o97dg

https://1drv.ms/p/s!AieUMe5bQRWh8qlurhV_ghxLZDor-A?e=ElL16f

https://youtu.be/sOaZsMFScE0

)

Sean: element timing is not the only one have this restriction. i.e, selection API also have similar restriction

Michal: Isolating Shadow DOM makes sense to me, just applying ET to the custom element, you may still be able to get a presentation time if we can nail the timing

… A bunch of Shadow DOM things that you can observe with ET

Jase: Elements in Shadow DOM should be implementation detail to anything inside

… On one side, just a block, I care when that blocks was rendered

… Some developers may think the block is doing complex stuff and want to know when those components are presented

Noam: Could work if we passed PerformanceObserver to Shadow Root or something, ways to expose it

Yoav: In the TPAC 2022 discussion, imposing opt-ins all the way down would be restrictive in terms of deployment

… e.g. a lot of deployments of nested Shadow Roots

… Forcing opt-in would be overly taxing

Michal: Biggest question we have a wonderful slideshow of a whole page made up of tiny elements, LCP being a tiny corner textbox of one page

… Now with container element in demo, the very first container element observer call represents the whole table

… Same timing as final LCP value of this page (in example built)

… Should the first paint of a container be what matters for LCP overall

… More relevant for LCP element

… Or do we want streams of paints within the container

… Last one?  Edit in a cell later on?  How do you define the most contentful paint of a stream of paints?

Yoav: What’s a container in a context of LCP?

Michal: This is a custom polyfill for a custom way to decorate?

… Was thinking this could potentially apply to LCP algorithm?

… This polyfill to understand if these conventions match user expectations, can they be applied to LCP algo

Yoav: we’d need to define an algorithm that magically finds containers

Jase: I don’t have a great answer to that

Michal: Going forward, as we play with this polyfill and observe streams of paints for containers, would be interesting to do analysis, this % of the container was painted after an update

… I could see the very first paint be a tiny portion, then a big update, then tiny updates, what should we go by?  Middle one?

Jase: How would you surface these updates?  Similar to what we showed today with new entries?

… When table was being painted they were in the same batch and render time

Michal: You get a long list of ET when that happens?  All size? Coordinates?

Jase: I don’t think there are coordinates in there?

Michal: If you had an intersection rect you could look at the full size of this paint

Jase: Theoretically yes. Take all of the paints in a batch and get the size for all of them, and report that

… Close to what you’re describing I think

… Would the developer need to do any work around that, or a calculation of algorithm, make the choice to decide this was the most significant one

Michal: With polyfill you could expose the data and leave up to the consumer to describe

… As we watch a polyfill how it works, will the initiation match that a single largest paint be the most contentful

Yoav: Now that we have a polyfill, is anyone in the room planning to try to use that in some form?

… Is it interesting enough for you to try to use, measure, see impact

Andy: I was going to create some more examples that match our original presentation, examples of things that we see in the wild and how they match

Yoav: What would it take for this polyfill to make its way into SpeedCurve’s JavaScript

Andy: Test on our own first, test in SC itself

Nic: We’d want to understand the performance implications. Companies that are using ET seem more suitable for using this

Andy: The folks we got using ET are pretty knowledgeable

Jase: Interested in trying this. The intersection rect idea seems interesting

… Would be great to have others look at the performance aspects of it

Nic: Thanks for the great demo and polyfill

Jase: how do we proceed?

Yoav: If you or other folks that have experimented with it come up with results to show to the group, can be an interesting follow-up

… If any more gaps are found where this is insufficient, or ET needs to better e.g. handle Shadow DOM or needs to be lazier, that could be interesting conclusions to bring back to the group

… Experimenting with polyfill, having conclusions and back to the group makes sense