Participants
- Yoav Weiss, Nic Jansma, Patrick Meenan, Barry Pollard, Michal Mocny, Dan Gayle, Noam Helfman, Guohui Deng, Carine Bournez, Alex Christensen, Amiya Gupta, Bas Schouten, Dave Hunt, Scott Haseley, Jennifer Strickland, Joone Hur, Jose Dapena Paz, Markl Ilic, Sergey Chernyshev
Admin
- TPAC agenda ideas - please add participation + ideas on stuff you want to talk about
- Container Timing Adoption
- Administrative work to do to move from WICG to W3C repo
- Next meeting: October 8 (earlier time slot)
Minutes
- Michal: Some perf entries are full page lifecycle and continue to get emitted forever.
- … not 100% consistent, e.g. resource Timing
- … So instead of polling in a loop, you should use performance observer and get notifications
- … “buffered” flag gives you a list from the performance timeline and give it to the observer
- … But the spec is that as soon as you construct your PO we copy the list and queue an observer.
- … There’s also a takeRecords call
- … So you can polyfill getEntriesByType using performance observer, which gives you the entries synchronously
- … used this in an observer when wanting to snapshot the last set of entries
- … The actual scheduling of the initial callback has some unique behaviors
- … The first callback will only be all the previously buffered entries and the next will contain followups
- … There may be expectation to only see old values before seeing new ones?
- … Questions:
- … 1. Is this a spec oversight?
- … 2. Is this behavior relied on?
- … A recent example for complexity - to support scroll timing with buffered, the browser needs to do all the book keeping, but can we be lazy and only create the entries once the page needs the entries?
- … You kinda can’t at the moment due to the sync nature
- Nic: After you take the initial buffer, a second call won’t get the entries?
- Michal: Every new observer gets the full list, but the callback will get called once for the old entries, and again for the new ones
- … Normally we’d cluster entries, but that doesn’t happen in that first callback
- Barry: The whole book keeping thing, you still get all the entries, right?
- Michal: Today the only entries you’d get with buffered: true are the ones that are already in the timeline. The browser has to do the book-keeping, but we can be lazier with constructing the performance entry.
- … Once you register your first PO, we have to construct, but not before
- … With Scroll Timing, that info is stored in the compositor.
- Barry: But there are no guarantees for a performance observer RE when it’d be emitted
- Michal: I guess the spec doesn’t guarantee that, but I doubt anyone implements it that way
- … I don’t know how existing users of PO would handle such a change
- Barry: My personal preference is that getEntriesByType is supported everywhere
- Michal: At the moment you can polyfill this, but it will break if we change that. Today takeRecords has to return something, but it could return nothing if we didn’t construct the entries
- … Currently specified to queue sync and I suggest to change to async
- Scott: Order is not guaranteed, but people may rely on it
- NoamH: Trying to understand the sync nature
- Michal: Queues the task sync, not the callback
- … If we have entries in the buffer, they need to be copied immediately
- … Can say that implementations can construct entries async
- NoamH: The tricky part would be takeRecords. Challenge is not breaking this
- Michal: takeRecords is used a lot at page unload. But we know in the past that the perf timeline can be mid-measurement, even if you call takeRecords
- NoamH: So people use it at beforeUnload and collect whatever is already there. Can’t break takeRecords
- Michal: Just suggesting to extend the initial gap, not break takeRecords
- Bas: The case where it might matter, is on page hide
- Michal: So you won’t be able to register new POs at page hide
- Nic: As long as you register your PO first you’d be OK
- Yoav: I’m sure people are relying on this, but how much is an interesting question.
- … ScrollTiming is one of the first where you’re collecting measurements at compositor, then when a PO is registered, it’s an IPC call away
- … We could optimistically move that data to the renderer, but it’s extra work
- Bas: And usually wasteful
- Yoav: What we could do here is just change that initial gap for this specific entry, where no one is relying on it right now, and not worry about compat, change the spec so that people won’t read the spec and rely on it
- Michal: PT could be left as-is
- … Other APIs could have some sort of <meta> tag to opt in, notify RUM so that it can be loaded later
- Bas: We limit the amount of entries that are buffered
- … General, no guarantees about synchronicity, in any specs
- … I think spec-wise you’re already good?
- Michal: What is the true interop, and expectations?
- Barry: Found some examples in Github searches
- Yoav: Decent hint we can do this for new entries, but maybe not back-port back
- … Value to providing measurements synchronously
- Bas: Then you should just be able to use getEntriesForType()
- Barry: Point was it was a footgun for metrics to be measured any point in time
- … We’ve taken you can’t get LCP after 5 seconds because browser knows better
- Yoav: At some point we decided all new things should be PO-only
- … Principled stance
- … If there’s significant costs to entry-creation or book-keeping (like moving data from compositor to renderer), it should be async
- Bas: What’s reason for Scroll Timing to support buffered at all?
- Michal: We don’t want scripts to load as early as possible and slow down loading
- … Incentivize not slowing down loading performance
- Bas: OTOH you incentivize browsers to do book-keeping regardless
- Michal: Very rarely-used feature which has high overhead? Or can browser do it efficiently enough that it doesn’t affect typical user?
- … CWV we measure anyway, so they’re as efficient as possible
- … Question of exposing to developer as an opt-in isn’t much of a lift
- Bas: For CWV entries may not be kept around in page, you keep more data around
- … For Scroll Timing, it’s harder to see why you’d want buffered entries
- Yoav: You want analytics to load as late as possible without loading data
- Bas: How often are scroll timing entries generated?
- Noam: Page Load time is most sensitive where it matters, it’d be interesting to understand scroll performance during that short period
- Michal: For ResourceTiming (RT), which also tracks data for getEntriesByType(), many sites don’t load this. So we could skip book-keeping. But many sites do, and they want all entries.
- … Provided there’s not a significant downside.
- … Opt-in has downsides
- Noam: Office-related code, .takeRecords() is not common, when it’s used, it’s used async. But we see it in Github
- Yoav: Simplest path forward to provide an exception for Scroll Timing
- … Not expose API to PT
- Michal: Provide hook to PT, so APIs can know when first registered observer was made
- … That would accompany a note where a spec could be lazy to include entries
- Barry: New flag to table in entryNames registry
- Noam: Other requirements we have from developers, it’s an option to consider
Paint Timing
- Scott: Going through Paint Timing implementations and cleaning up.
- … Wanted to talk about a security issue AI bots picked up
- … We have an entropy check where we calculate the content size of the image and filter our low entropy images. Dunno if other browsers implemented this with LCP
- … But content-length is TAO-protected.
- … Since the developer controls the layout size of the image, they can effectively binary search and find the bytes of the image
- … We’re clamping it by intrinsic size, but here we’re downscaling it to find the size
- … Altering the size of the layout to get the content length of the image - same image over time
- … The image would have to be visible
- Yoav: I’m surprised by layout size here instead of just images intrinsic size
- Scott Haseley: May just be able to use intrinsic size, just get 1 bit of information
- … I think we’d have to redo research to ensure we’re excluding the right things here or not
- … Patch this to add a CORS check, if same-origin we do entropy check otherwise skip it
- … ResourceTiming equivalent is content size (encodedBodySize, etc)
- … Issue 220 was TAO protected, but moving towards CORS protected
- … data-uri was something we wanted to exclude
- … We’re still getting the bulk of what we wanted to protect against in the first place
- Barry: Cross-origin images are already coarsened, could we do that here?
- Michal: We coarsen the timing by 4ms, this is different, it’s eligible-or-not
- … Similar thing with NavigationTiming Confidence
- … We could just flip a coin and sometimes allow it to pass, but the numbers are more significant here
- … Last time Ian did this and found thresholds, changed rate at which origins passed LCP. Was doing LCP hacks (intentional or accidental), those are the biggest changes, and I suspect they still would be
- … Images that passed with CORS check may then fail
- … Just won’t have entropy check, non-CORS, be large, low entropy, that total set all has to be true for it to be an accidental oversight, feels low but who knows
- … We should maybe just be using intrinsic size
- Yoav: Already fixed in Chromium?
- Scott: Fix behind a flag
- … Might run a holdback to see what the impact was
- … Change low enough we’re comfortable with just landing this
- Bas: Webkit and Firefox, neither implement content-size check
- … No WPT test
- … We don’t have same incentives as much as Google does, to game this
- … Puts us in a slightly different position
- … If there’s a safe way to implement then it doesn’t hurt too much
- … At that point we’ve already forgotten about size of file
- Michal: Not wrong about incentives, but there were some non-performance experts plugins that would make sites “pass”
- … Sometimes folks are thinking they’re doing the right thing, but maybe they aren’t
- … There’s user-value here too
- Bas: Possible to implement, plumbing should be easy
- … Webkit has open outstanding bug I found, might be worth commenting on it
- Barry: Even though we did add this to combat gaming, LCP was added to avoid placeholder images
- Bas: Some arbitrary choice we’ve made to decide what is LCP
- Scott: There are images that are used in LCP tests that are solid blue rectangle, that passes
- … If we would have done this, realizing we were exposing values originally, we wouldn’t have shipped it
- Yoav: Observable, but seems like the right thing, no strong objections
- Bas: Spec issue?
- Scott: Haven’t filed one yet, will file one