Skip to content

Plotly adapter renders every figure twice on page load #32

Description

@jvdd

Plotly adapter renders every figure twice on page load

What happens

init.js calls Plotly.newPlot with empty stub traces for every figure at
script top level, awaits those promises, binds events, and only then sends
the init POST /dashboard/update. The response is drawn with Plotly.react.

Measured on gecko (headless Chromium 151, Plotly 3.0.0, one line trace,
1M rows in memory, 7 repeats):

stage ms
newPlot with empty stub traces 28.2
flexviz JS between newPlot and fetch 0.5
server + transfer 4.2
Plotly.react with 1000 points 15.9
render barrier 6.5

A single newPlot with the same 1000 points costs 31.7 ms. So the stub
render adds about 10 ms of duplicate Plotly work, and the page cannot send
the request until the stub render is done. The cost is per page load, flat
in trace count, and independent of row count.

Fix

Send the init update as soon as the runtime is loaded, and let the first
Plotly.react do the initial draw. Plotly.react on a div that has no
_fullLayout calls newPlot internally (plotly.js plot_api.js,
function react), so render.js needs no change.

Startup order becomes:

  1. Fire restoreDashboardFromSpec() (the init POST) immediately.
  2. When a figure's first react resolves, bind that figure once: Plotly
    event handlers (plotly_relayout, plotly_selected, ...), the
    ResizeObserver, panel controls, setFigureMode for non-cartesian
    figures, and the mode indicator.
  3. Any figure the init response does not touch gets one newPlot with its
    stub traces after the response, so the div exists and events bind.

Estimated window: about 45 ms instead of 58 ms in the benchmark harness.
Users see 10 to 13 ms less on page load.

Trade-offs

  • The panel is blank until the first response arrives. Today an empty axes
    frame shows at once. A CSS placeholder covers this if it matters.
  • A cheaper variant keeps the stub but fires the fetch in parallel with it.
    That saves only about 5 ms because the request finishes long before the
    stub render does.
  • The benchmark probe (flexviz_probe.js) keys its clock start on the
    first newPlot call. After this change the clock must key on the request.

Scope

flexviz/adapters/js/plotly/init.js only, plus browser tests for init,
relayout, selection, and multi-figure dashboards. Roughly one day.

Activity

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

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions