zpl.tools
Performance

zpl.tools and zebrash

Response time, accepted page counts and response size, measured 2026-08-17

zebrash is a local engine: Go library behind a local HTTP wrapper. This page compares it with zpl.tools engine — the same renderer as the API, on localhost. Neither side crosses a network. A local engine is never compared with the hosted zpl.tools API, because the API adds network time that a local call does not carry.

Response time

Median response time, orderful style
  • zpl.tools engine
  • zebrash
01,0002,0003,0000100200300400500Pages per requestMedian response, ms2,940 ms276 ms
Orderful style, PNG.
Values behind this chart
Engine1 p2 p3 p4 p5 p10 p15 p20 p25 p30 p35 p40 p45 p50 p75 p100 p150 p200 p300 p500 p
zpl.tools engine19 ms12 ms20 ms11 ms21 ms21 ms25 ms26 ms40 ms29 ms43 ms38 ms52 ms49 ms73 ms86 ms85 ms130 ms181 ms276 ms
zebrash36 ms66 ms93 ms90 ms137 ms265 ms434 ms578 ms713 ms814 ms941 ms1,090 ms1,225 ms1,392 ms2,134 ms2,940 ms

On one page, zpl.tools engine answers in a median 19 ms and zebrash in 36 ms, a factor of 1.9. At 100 pages, the largest packet the benchmark sent to both engines, the medians are 86 ms and 2,940 ms. zpl.tools engine rendered 500 pages in a median 276 ms, and 500 pages is where the benchmark stopped — the renderer sets no page limit. The benchmark measured zebrash to 100 pages.

Response size

PDF response size, orderful style
  • zpl.tools engine
  • zebrash
0 B488.3 KB976.6 KB1.43 MB0100200300400500Pages per requestResponse body1.40 MB87.0 KB
Orderful style, PNG.
Values behind this chart
Engine1 p2 p3 p4 p5 p10 p15 p20 p25 p30 p35 p40 p45 p50 p75 p100 p150 p200 p300 p500 p
zpl.tools engine87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB87.0 KB
zebrash10.5 KB18.0 KB28.4 KB39.0 KB57.3 KB125.9 KB199.7 KB274.9 KB343.3 KB399.9 KB461.5 KB538.4 KB611.2 KB684.5 KB1.02 MB1.40 MB

A one-page PNG from zpl.tools engine is 87.0 KB. At 500 pages the same response is 87.0 KB: 1.0 times the size for 500 times the pages. At 100 pages, the response is 87.0 KB against 1.40 MB from zebrash.

Corpora

Each corpus is one request body, repeated at every page count. A corpus reaches this page only where the run measured both engines on it.

Simple label

Labelary's own example label, duplicated per page. Every page carries the same label.

Pageszpl.tools engine p50zpl.tools engine p90zpl.tools engine p95zebrash p50zebrash p90zebrash p95
120 ms22 ms23 ms51 ms52 ms52 ms
1027 ms28 ms28 ms278 ms283 ms284 ms
5047 ms49 ms49 ms1,318 ms1,332 ms1,347 ms
10066 ms69 ms70 ms2,663 ms2,701 ms2,703 ms
500195 ms206 ms208 ms

GS1 graphics label

A real retailer label with embedded ~DG graphics, duplicated per page. Every page carries the same label.

Pageszpl.tools engine p50zpl.tools engine p90zpl.tools engine p95zebrash p50zebrash p90zebrash p95
117 ms18 ms18 msrejectedrejectedrejected
1032 ms32 ms33 msrejectedrejectedrejected
5046 ms47 ms47 msrejectedrejectedrejected
10063 ms93 ms166 msrejectedrejectedrejected
500143 ms147 ms147 ms

Orderful style

Orderful retail compliance labels, a different label on every page. Every page carries a different label, so no engine can reuse a page it already rendered.

Pageszpl.tools engine p50zpl.tools engine p90zpl.tools engine p95zebrash p50zebrash p90zebrash p95
119 ms20 ms20 ms36 ms45 ms45 ms
1021 ms25 ms25 ms265 ms268 ms268 ms
5049 ms58 ms63 ms1,392 ms1,417 ms1,422 ms
10086 ms87 ms88 ms2,940 ms2,974 ms2,982 ms
500276 ms280 ms280 ms

SPS Style

The same retailer labels delivered as ~DG bitmap pages, the SPS Commerce way. Every page carries a different label, so no engine can reuse a page it already rendered.

Pageszpl.tools engine p50zpl.tools engine p90zpl.tools engine p95zebrash p50zebrash p90zebrash p95
113 ms13 ms13 ms62 ms64 ms66 ms
1036 ms40 ms40 ms431 ms437 ms439 ms
5068 ms76 ms77 ms2,014 ms2,042 ms2,066 ms
100104 ms106 ms106 ms4,102 ms4,138 ms4,145 ms

Method

k6 drives every point, one request at a time, 10 iterations per point, 5 past 150 pages. A one-page point carries 10 samples.

Client: k6, one request at a time. Both hosted engines measured in the same session from a Hetzner ccx13 (dedicated vCPU) in the fsn1 datacenter, Germany — network RTT included, the same for both sides. Local engines measured on a MacBook Pro (Apple Silicon), no network crossed; the zpl.tools, zebrash, BinaryKits and Neodynamic summaries carry over from the 2026-08-09 run, because no code in the render path changed between them. labelize was added on 2026-08-17 and measured on the same MacBook, at one page only — see below.

Measured 2026-08-17. The harness is benchmarks/run.sh, and its header names the local servers each engine needs. To repeat the run:

./benchmarks/run.sh
node scripts/distill-benchmarks.mjs
node scripts/generate-performance-pages.mjs

The first command measures, the second writes website/lib/performance-data.json, and the third writes this page from it.