Performance

Every example in the plot-type reference gallery serialized to static SVG and to self-contained interactive HTML, with output sizes. (The real applications gallery is not timed here: its figures are variations on the same shapes, and timing another hundred of them would treble the runtime without adding a row that says anything new.) Interactive HTML embeds the same SVG plus the per-axes data the toolbar needs for zoom / point-picking (the picked values, and mesh z grids), so it is larger and slower than SVG – most for mesh-heavy figures.

Best of 5 runs, one machine. Regenerate with python benchmarks/example_timings.py.

Against other libraries

The same four figures built and serialized to SVG by each library, using its own idiomatic API and no global state on any side. matplotlib goes through the object-oriented FigureCanvasSVG rather than pyplot; xy renders headlessly through Chart.to_svg(). xy facets by a data column rather than by an arbitrary grid, so its 8x8 case is 64 groups of one long-form table – the idiomatic equivalent, not a handicap.

These measure time to produce a static file, which is the axis plotpress optimizes. It is not the axis xy optimizes: its Rust core decimates by screen resolution for interactive exploration of large data, and a single static render does not exercise that.

Scenario

plotpress (time / size)

matplotlib (time / size)

xy (time / size)

line_100k_points

8.8 ms / 17 KiB

41.1 ms / 24 KiB

2.5 ms / 31 KiB

scatter_5k_points

14.9 ms / 137 KiB

118.1 ms / 533 KiB

22.2 ms / 360 KiB

pcolormesh_300x300

9.2 ms / 45 KiB

5661.0 ms / 15.4 MiB

15.6 ms / 95 KiB

many_axes_8x8_grid

36.1 ms / 336 KiB

1317.6 ms / 331 KiB

58.9 ms / 361 KiB

Per-example output

Example

Axes

SVG

SVG size

HTML

HTML size

pairwise/plot_01_line

1

1.6 ms

10 KiB

3.0 ms

85 KiB

pairwise/plot_02_scatter

1

3.1 ms

44 KiB

3.9 ms

119 KiB

pairwise/plot_03_bar

1

0.5 ms

4 KiB

0.9 ms

75 KiB

pairwise/plot_04_barh

1

0.4 ms

4 KiB

0.8 ms

75 KiB

pairwise/plot_05_stem

1

0.3 ms

5 KiB

0.6 ms

76 KiB

pairwise/plot_06_step

1

0.3 ms

3 KiB

0.6 ms

73 KiB

pairwise/plot_07_fill_between

2

4.0 ms

21 KiB

5.6 ms

104 KiB

pairwise/plot_08_stackplot

1

0.5 ms

4 KiB

0.9 ms

75 KiB

pairwise/plot_09_loglog

3

2.2 ms

14 KiB

3.4 ms

88 KiB

pairwise/plot_10_reference_lines

1

1.8 ms

16 KiB

3.0 ms

94 KiB

pairwise/plot_11_broken_barh

1

0.4 ms

3 KiB

0.9 ms

74 KiB

pairwise/plot_12_stairs

1

0.3 ms

3 KiB

0.6 ms

74 KiB

pairwise/plot_13_axline

1

0.4 ms

4 KiB

0.9 ms

75 KiB

pairwise/plot_14_hlines_vlines

2

1.6 ms

14 KiB

2.8 ms

92 KiB

pairwise/plot_15_linestyles

2

3.8 ms

29 KiB

6.5 ms

116 KiB

distributions/plot_01_hist

1

1.0 ms

8 KiB

1.4 ms

80 KiB

distributions/plot_02_boxplot

1

0.3 ms

4 KiB

0.6 ms

75 KiB

distributions/plot_03_errorbar

1

0.4 ms

5 KiB

0.6 ms

75 KiB

distributions/plot_04_violin

1

1.5 ms

10 KiB

2.7 ms

85 KiB

distributions/plot_05_eventplot

1

1.2 ms

16 KiB

1.9 ms

88 KiB

distributions/plot_06_hist2d

1

0.7 ms

6 KiB

1.7 ms

82 KiB

distributions/plot_07_pie

1

0.1 ms

1 KiB

0.3 ms

72 KiB

distributions/plot_08_hexbin

1

13.8 ms

63 KiB

22.4 ms

151 KiB

gridded_data/plot_01_imshow

1

1.7 ms

17 KiB

6.3 ms

164 KiB

gridded_data/plot_02_pcolormesh

1

17.7 ms

50 KiB

40.3 ms

544 KiB

gridded_data/plot_03_contour

1

32.4 ms

87 KiB

37.0 ms

235 KiB

gridded_data/plot_04_quiver

1

2.1 ms

27 KiB

3.1 ms

104 KiB

gridded_data/plot_05_contourf

1

18.2 ms

12 KiB

82.9 ms

1.3 MiB

gridded_data/plot_06_curvilinear_mesh

1

290.3 ms

41 KiB

283.9 ms

149 KiB

gridded_data/plot_07_gouraud

2

184.7 ms

289 KiB

184.0 ms

372 KiB

gridded_data/plot_08_lognorm

2

7.0 ms

29 KiB

29.5 ms

521 KiB

gridded_data/plot_09_matshow

1

0.6 ms

7 KiB

1.0 ms

78 KiB

gridded_data/plot_10_spy

1

0.4 ms

3 KiB

1.0 ms

77 KiB

gridded_data/plot_11_colormap_reference

5

4.0 ms

42 KiB

11.6 ms

180 KiB

multi_axes/plot_01_subplots

4

2.5 ms

24 KiB

4.7 ms

111 KiB

multi_axes/plot_02_annotations

1

0.6 ms

6 KiB

1.2 ms

78 KiB

multi_axes/plot_03_twin_axes

4

3.1 ms

24 KiB

5.1 ms

110 KiB

multi_axes/plot_04_shared_colorbar

6

3.7 ms

22 KiB

12.2 ms

213 KiB

animation/plot_01_plot_frames

1

0.7 ms

6 KiB

4.8 ms

110 KiB

animation/plot_02_pcolormesh_frames

4

3.8 ms

23 KiB

246.8 ms

3.7 MiB

scale/plot_01_many_axes

500

395.9 ms

2.7 MiB

836.3 ms

7.5 MiB

scale/plot_02_million_point_line

1

156.8 ms

47 KiB

184.9 ms

117 KiB

scale/plot_03_multimillion_mesh

1

320.6 ms

775 KiB

419.8 ms

2.1 MiB

scale/plot_04_thousand_series

1

887.8 ms

6.9 MiB

1362.2 ms

12.1 MiB

scale/plot_05_axes_grid_lines

900

20173.4 ms

2.4 MiB

58817.4 ms

3.9 MiB

scale/plot_06_shared_colorbar_lognorm

144

81.5 ms

514 KiB

236.8 ms

2.5 MiB

scale/plot_07_matplotlib_comparison

1

0.9 ms

5 KiB

1.3 ms

76 KiB

scale/plot_08_vector_over_raster

1

266.3 ms

600 KiB

437.4 ms

3.2 MiB

scale/plot_09_output_scaling

1

1.6 ms

7 KiB

2.3 ms

79 KiB

scale/plot_10_many_groups_with_colorbars

1

0.3 ms

3 KiB

0.6 ms

74 KiB

The scale/plot_01_many_axes row is the deliberate stress case: 500 independent pcolormesh axes on one figure. Its interactive HTML is dominated by the 500 embedded mesh z grids; lower fig.to_html(pick_precision=...) (or fig.save(..., pick_precision=...)) to trade readout precision for a smaller file, or cap the total embedded amount directly with pick_max_mesh_cells / pick_max_points – a mesh over the cap is block-averaged down to it rather than dropped, so a click still answers with a real, if coarser, value.

Binary vs. JSON pick data

fig.to_html()/fig.save(...html) embed long point-pick arrays (mesh z grids, animated line frames) as base64 float32 bytes by default (binary_pick_data=True) rather than JSON number text. Below is every example above, both ways: most are small enough that neither the array-length threshold nor the file size difference matters: the JSON version is well under a point-pick array’s own threshold to begin with. It shows up once a mesh or a long series does most of the work, which is exactly the scale/ rows.

Example

Binary

Binary size

JSON

JSON size

Size

Time

pairwise/plot_01_line

3.0 ms

85 KiB

2.7 ms

88 KiB

1.04x

0.88x

pairwise/plot_02_scatter

3.9 ms

119 KiB

3.5 ms

123 KiB

1.03x

0.89x

pairwise/plot_03_bar

0.9 ms

75 KiB

0.8 ms

75 KiB

0.99x

0.99x

pairwise/plot_04_barh

0.8 ms

75 KiB

0.7 ms

75 KiB

0.99x

0.81x

pairwise/plot_05_stem

0.6 ms

76 KiB

0.5 ms

76 KiB

0.99x

0.95x

pairwise/plot_06_step

0.6 ms

73 KiB

0.5 ms

73 KiB

0.99x

0.92x

pairwise/plot_07_fill_between

5.6 ms

104 KiB

5.1 ms

112 KiB

1.08x

0.90x

pairwise/plot_08_stackplot

0.9 ms

75 KiB

0.9 ms

75 KiB

0.99x

0.92x

pairwise/plot_09_loglog

3.4 ms

88 KiB

2.9 ms

91 KiB

1.03x

0.85x

pairwise/plot_10_reference_lines

3.0 ms

94 KiB

2.7 ms

99 KiB

1.05x

0.93x

pairwise/plot_11_broken_barh

0.9 ms

74 KiB

0.8 ms

73 KiB

0.99x

0.93x

pairwise/plot_12_stairs

0.6 ms

74 KiB

0.5 ms

73 KiB

0.99x

0.90x

pairwise/plot_13_axline

0.9 ms

75 KiB

0.7 ms

75 KiB

1.00x

0.78x

pairwise/plot_14_hlines_vlines

2.8 ms

92 KiB

2.7 ms

97 KiB

1.06x

0.95x

pairwise/plot_15_linestyles

6.5 ms

116 KiB

6.1 ms

129 KiB

1.11x

0.93x

distributions/plot_01_hist

1.4 ms

80 KiB

1.3 ms

80 KiB

1.00x

0.93x

distributions/plot_02_boxplot

0.6 ms

75 KiB

0.5 ms

74 KiB

0.99x

0.85x

distributions/plot_03_errorbar

0.6 ms

75 KiB

0.6 ms

75 KiB

0.99x

0.90x

distributions/plot_04_violin

2.7 ms

85 KiB

2.1 ms

88 KiB

1.03x

0.79x

distributions/plot_05_eventplot

1.9 ms

88 KiB

1.7 ms

89 KiB

1.01x

0.90x

distributions/plot_06_hist2d

1.7 ms

82 KiB

1.4 ms

85 KiB

1.05x

0.82x

distributions/plot_07_pie

0.3 ms

72 KiB

0.2 ms

72 KiB

0.99x

0.75x

distributions/plot_08_hexbin

22.4 ms

151 KiB

22.5 ms

166 KiB

1.11x

1.00x

gridded_data/plot_01_imshow

6.3 ms

164 KiB

8.8 ms

234 KiB

1.43x

1.40x

gridded_data/plot_02_pcolormesh

40.3 ms

544 KiB

53.6 ms

871 KiB

1.60x

1.33x

gridded_data/plot_03_contour

37.0 ms

235 KiB

39.5 ms

308 KiB

1.31x

1.07x

gridded_data/plot_04_quiver

3.1 ms

104 KiB

2.8 ms

108 KiB

1.04x

0.92x

gridded_data/plot_05_contourf

82.9 ms

1.3 MiB

126.0 ms

2.4 MiB

1.88x

1.52x

gridded_data/plot_06_curvilinear_mesh

283.9 ms

149 KiB

281.6 ms

184 KiB

1.23x

0.99x

gridded_data/plot_07_gouraud

184.0 ms

372 KiB

184.9 ms

382 KiB

1.03x

1.00x

gridded_data/plot_08_lognorm

29.5 ms

521 KiB

45.4 ms

927 KiB

1.78x

1.54x

gridded_data/plot_09_matshow

1.0 ms

78 KiB

0.9 ms

78 KiB

1.00x

0.87x

gridded_data/plot_10_spy

1.0 ms

77 KiB

0.8 ms

78 KiB

1.02x

0.81x

gridded_data/plot_11_colormap_reference

11.6 ms

180 KiB

10.9 ms

232 KiB

1.28x

0.95x

multi_axes/plot_01_subplots

4.7 ms

111 KiB

4.5 ms

125 KiB

1.12x

0.97x

multi_axes/plot_02_annotations

1.2 ms

78 KiB

1.2 ms

80 KiB

1.02x

0.95x

multi_axes/plot_03_twin_axes

5.1 ms

110 KiB

4.9 ms

121 KiB

1.10x

0.96x

multi_axes/plot_04_shared_colorbar

12.2 ms

213 KiB

15.2 ms

306 KiB

1.44x

1.25x

animation/plot_01_plot_frames

4.8 ms

110 KiB

4.0 ms

140 KiB

1.27x

0.82x

animation/plot_02_pcolormesh_frames

246.8 ms

3.7 MiB

352.0 ms

6.1 MiB

1.64x

1.43x

scale/plot_01_many_axes

836.3 ms

7.5 MiB

919.7 ms

11.7 MiB

1.55x

1.10x

scale/plot_02_million_point_line

184.9 ms

117 KiB

184.5 ms

117 KiB

1.00x

1.00x

scale/plot_03_multimillion_mesh

419.8 ms

2.1 MiB

467.5 ms

3.3 MiB

1.58x

1.11x

scale/plot_04_thousand_series

1362.2 ms

12.1 MiB

1460.5 ms

17.3 MiB

1.42x

1.07x

scale/plot_05_axes_grid_lines

58817.4 ms

3.9 MiB

58642.3 ms

5.1 MiB

1.29x

1.00x

scale/plot_06_shared_colorbar_lognorm

236.8 ms

2.5 MiB

285.1 ms

4.1 MiB

1.69x

1.20x

scale/plot_07_matplotlib_comparison

1.3 ms

76 KiB

1.3 ms

76 KiB

0.99x

0.95x

scale/plot_08_vector_over_raster

437.4 ms

3.2 MiB

531.2 ms

5.6 MiB

1.75x

1.21x

scale/plot_09_output_scaling

2.3 ms

79 KiB

2.2 ms

78 KiB

0.99x

0.97x

scale/plot_10_many_groups_with_colorbars

0.6 ms

74 KiB

0.5 ms

74 KiB

0.99x

0.90x

“Size”/”Time” are JSON relative to binary – 2.0x under Size means the JSON payload is twice the binary one’s size; under Time means it took twice as long to build. A ratio near 1.0x on a small figure means the encoder found nothing worth switching: every array in it was already under the threshold where a base64 wrapper costs more than it saves.