Skip to content

Resize timing check can start measuring before the hardware charts finish their first animation #495

Closed

Description

@stephaniehobson

tests/playwright/specs/fixtures/resize.spec.js (added in #409) failed all three attempts in CI on #493: https://github.com/mozilla/ensemble/actions/runs/42708249217/job/129470673505. It measured 1095, 6946 and 1023 ms of long tasks against a 1000 ms budget. #493 does not change anything this test exercises: the same commits passed CI on another branch a few minutes later, main passes, and the spec passes 8 out of 8 runs locally.

The test starts its PerformanceObserver once the last chart's <svg> is visible. That may be too early. In src/components/views/MetricsGraphics.jsx, the first draw in componentDidMount is not animated (metrics-graphics defaults to animate_on_load: false), but any later update with different data is: transition_on_update defaults to true, which means a 1000 ms line transition. If a chart is drawn and then redrawn with new data while the page loads, that transition can still be running when measuring starts, and its cost gets counted against the resize. 6946 ms is close to the roughly 6 s the spec's comment gives for animating lines on resize, which fits this explanation. It hasn't been confirmed.

Two possible fixes, keeping the 1000 ms budget:

  • Before starting the observer, wait until no chart transition is still running, for example by waiting until the line paths stop changing or by checking for active d3 transitions.
  • Or wait for the main thread to go quiet first: start a long-task observer and only begin the resize sequence once no long task has been reported for some interval.

Checking first whether the hardware charts really do get an animated update during load (more than one MG.data_graphic call per chart before the resize starts) would confirm or rule out this explanation.

Activity

  1. stephaniehobson commented on Nov 9, 2026

    @stephaniehobson
    CollaboratorAuthor

    I checked the explanation above before trying either fix, and it doesn't hold. No chart animates during page load. The failures come from a fixed wall-clock budget measured on a slower runner, and from tracing on the retry.

    I ran the steps from resize.spec.js with a probe that records every write to a .mg-main-line path's d attribute and every long task:

    Conditions d writes before measuring d writes during resize Long-task total
    Local, 4 runs 95 95 186–197 ms
    4× CPU throttle, 4 runs 95 95 996–1024 ms
    6× CPU throttle, 4 runs 95 95 1414–1431 ms
    Tracing on, no throttle, 3 runs 95 95 159–169 ms
    Tracing on + 4× throttle, 3 runs 95 665 6459–6591 ms
    • The charts don't redraw during load. The 11 charts have 95 lines between them, and each line gets exactly one d write before measuring starts. That's one MG.data_graphic call per chart and no transition, which would write d dozens of times per line. This held at every throttle level.
    • The ~1000 ms failures are the resize itself. Locally the resize blocks for about 190 ms. At 4× throttle it comes to about 1000 ms, which matches the 1095 and 1023 ms CI measured. Every long task falls after measuring starts.
    • The 6946 ms failure is most likely the traced retry. playwright.config.js sets trace: 'on-first-retry', so attempt 2 runs with tracing. Tracing slows each setViewportSize step past ChartContainer's 150 ms resize debounce, so every chart redraws at each of the seven widths instead of once at the end. The writes are exactly 7 × 95, so it's seven full redraws, not animation frames. That it lands near the spec's ~6 s figure for animated lines is a coincidence.

    Both fixes proposed above wait for a transition that never runs, so neither would help.

    New direction

    Assert what the test is meant to guard instead of timing it. The spec's comments name two regressions: lines animating on resize, and charts redrawing on every resize event. Both can be checked directly by counting line redraws during the resize sequence: exactly one per chart, with no transition frames. That doesn't depend on runner speed. The 1000 ms long-task budget goes, or becomes a much looser backstop. Turning tracing off for this spec would also keep the retry's conditions the same as the first attempt's.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions