Benchmark
JairoSVG vs EchoSVG vs JSVG vs CairoSVG
Benchmark comparing SVG → PNG conversion across four libraries:
- JairoSVG (Java 25) — This project
- JSVG (Java) — Lightweight SVG renderer, weisj/jsvg
- EchoSVG (Java) — Batik fork, css4j/echosvg
- CairoSVG (Python) — Native C rendering via Cairo, cairosvg.org
Results
Each test case was run with 50 warmup iterations and 500 measurement iterations.
| Test Case | JairoSVG | JSVG | EchoSVG | CairoSVG | JairoSVG vs EchoSVG |
|---|---|---|---|---|---|
| Simple shapes | 4.3 ms | 4.3 ms | 20.9 ms | 5.7 ms | 4.8x faster |
| Gradients + transforms | 5.8 ms | 5.8 ms | 169.5 ms | 12.7 ms | 29x faster |
| Complex paths + text | 5.4 ms | 5.4 ms | 29.7 ms | 6.1 ms | 5.5x faster |
| Defs + use + clipPath | 4.8 ms | 4.7 ms | 18.0 ms | 6.3 ms | 3.7x faster |
| Markers + dashed strokes | 5.9 ms | 5.8 ms | 22.8 ms | 8.5 ms | 3.9x faster |
Analysis
- JairoSVG is 3–29× faster than EchoSVG across all test cases
- JairoSVG is on par with JSVG — both use Java2D for rendering
- JairoSVG is 1–2.6× faster than CairoSVG despite CairoSVG using a native C rendering backend
- JairoSVG achieves competitive performance through:
- Pre-compiled regex patterns
- Cached SAX parser factories
- Object reuse (GeneralPath.reset())
- Efficient string processing
- Sub-region effect buffers for filters and masks
PNG Output File Sizes
JairoSVG produces the smallest PNGs overall — 8.0% smaller than CairoSVG, 11.5% smaller than JSVG, and 17.3% smaller than EchoSVG:
| Test Case | JairoSVG | EchoSVG | CairoSVG | JSVG |
|---|---|---|---|---|
| Basic shapes | 6,718 | 8,159 | 8,920 | 7,031 |
| Gradients | 25,554 | 25,018 | 23,637 | 26,410 |
| Complex paths | 12,657 | 16,936 | 15,633 | 12,730 |
| Text rendering | 13,276 | 19,125 | 16,317 | 15,626 |
| Transforms | 5,461 | 5,261 | 6,001 | 5,827 |
| Stroke styles | 3,363 | 5,038 | 4,478 | 4,074 |
| Opacity blend | 8,409 | 10,201 | 9,853 | 8,788 |
| Viewbox aspect | 10,492 | 12,769 | 11,444 | 12,147 |
| CSS styling | 7,755 | 11,144 | 10,816 | 8,653 |
| Use and defs | 5,646 | 6,122 | 9,712 | 6,144 |
| Star polygon | 6,228 | 8,862 | 8,911 | 6,455 |
| Nested svg | 10,926 | 12,522 | 11,880 | 12,101 |
| Patterns | 9,532 | 11,832 | 11,095 | 11,043 |
| Clip paths | 9,342 | 10,558 | 13,552 | 10,253 |
| Masks | 5,692 | 5,566 | 1,161 | 6,209 |
| Markers | 6,334 | 8,117 | 8,378 | 6,727 |
| Filters | 28,934 | 24,063 | 8,520 | 32,346 |
| Embedded image | 9,432 | 11,994 | 21,228 | 11,642 |
| Text advanced | 18,801 | 26,256 | 23,864 | 19,756 |
| Blend modes | 12,005 | 16,216 | 12,505 | 15,773 |
| Fe tile | 1,456 | 2,009 | 1,768 | 1,489 |
| Feimage URI | 2,539 | 4,385 | 3,225 | 3,666 |
| Feimage ref | 2,705 | 3,431 | 4,868 | 4,265 |
| Localized masks | 18,389 | 17,868 | 13,218 | 20,239 |
| Total | 241,646 | 283,452 | 260,984 | 269,394 |
Test SVGs
Simple shapes: Rectangle, circle, ellipse, line, polygon, polyline with various fills and strokes.
Gradients + transforms: Linear and radial gradients with transforms, opacity, and gradient units.
Complex paths + text: Full path commands (M, L, C, S, Q, T, A), text with font properties, nested groups, clip paths.
Defs + use + clipPath: Definition elements, <use> references, clip paths, nested structure.
Markers + dashed strokes: Path markers (start/mid/end), dashed stroke arrays, line caps and joins.
Running the Benchmark
Prerequisites: JBang, Python 3 with CairoSVG (pip install cairosvg), Java 25+.
# Install JairoSVG to local Maven repo
./mvnw install -DskipTests
# Run benchmark
jbang comparison/benchmark/benchmark.java
# Run without progress bar (CI mode)
jbang comparison/benchmark/benchmark.java --no-progress
The benchmark script is in the comparison folder: comparison/benchmark/benchmark.java. See comparison/README.md for full results, PNG file size comparisons, and feature matrices.


