Plot Update Comparison#

There are a couple of different “costs” asscociated with rendering plots and images. There is usually a Python-side cost as well as a browser-side rendering cost. We’ve broken down those two costs here comparing different libraries for the first cost. The second is harder to measure. We’ve done it for anyplotlib but doing it for ipympl, bokeh and plotly is a little more difficult.

  • Python pre-render — everything that happens in the Python process before bytes reach the browser (timeit-measured, no browser needed).

  • JS canvas render — the actual canvas paint time measured inside headless Chromium via Playwright (anyplotlib only; see the third and fourth charts).

Note

The Python-side timings are pure-Python timeit benchmarks — no browser is involved. The JS render timings use Playwright’s requestAnimationFrame loop and window._aplTiming to measure inter-frame intervals in a real Chromium renderer.

What each Python measurement covers#

Library

What is timed

anyplotlib

plot.set_data(data) — float → uint8 normalise → base64 encode → LUT rebuild → state-dict assembly → json.dumps → traitlet dispatch to JS renderer.

ipympl

im.set_data(data); fig.canvas.draw() — fully rasterises the figure to an Agg pixel buffer, then encodes it as a PNG blob ready for the ipympl comm channel. This is the complete Python-side cost before the PNG is sent to the browser.

Plotly

fig.data[0].z = data.tolist(); fig.to_json() — builds the full JSON blob that Plotly.js receives; every float becomes a decimal string. Plotly.js WebGL/SVG render is additional.

Bokeh

source.data = {"image": [data]}; json_item(p) — builds the full JSON document patch that Bokeh.js receives. Canvas render is additional.


2-D image update (Python pre-render, all four libraries)#


1-D line update (Python pre-render, all four libraries)#


anyplotlib: Python prep vs JS canvas render#

The two charts above show only the Python-side cost. The charts below add the JS render time for anyplotlib measured inside a real Chromium renderer via Playwright (window._aplTiming populated by _recordFrame() in figure_esm.js). The sum of both bars is the total time-to-pixel for an anyplotlib update.

For ipympl, Plotly, and Bokeh the browser render cost is additional but not captured here — measuring it requires running their respective JS engines in a live browser session.

Note

If Playwright is not installed the JS bars are absent (zero height) and a UserWarning is emitted at import time. Install Playwright (pip install playwright && playwright install chromium) to populate the JS timing columns.

2D Image Plotting Costs#


Scatter Plotting Costs#

Total running time of the script: (2 minutes 54.019 seconds)

Gallery generated by Sphinx-Gallery