Line Wrapping Benchmark

This benchmark tests the performance of line wrapping and simple general layouting. The Project Gutenberg text of Homer’s Odyssey is used for this purposes.

Benchmark Setup

The text of the Odyssey is arranged on pages of the dimension WIDTHx1000 where WIDTH is set to different values (400, 200, 100 and 50 by default). Additionally, all widths are combined once with the standard PDF Type1 font Times-Roman and once with a TrueType font (DejaVu Sans by default).

In the case of pages with a width of 400 no line wrapping needs to be done because each line in the source text is shorter than 400 points. In the other cases lines need to be actually wrapped and the number of pages increases. With a width of 50 even words need sometimes to be broken.

Each benchmark script can be invoked standalone in the following way: script-executable TXT_FILE WIDTH OUTPUT_FILE [TTF_FILE].

The performance of the libraries hugely depends on how the input text is provided: Some are very fast when processing the whole input file at once, others only when processing the input line by line. The fastest method was always chosen.

The list of the benchmarked libraries:

HexaPDF

Homepage: http://hexapdf.gettalong.org
Language: Ruby
Version: Latest version

HexaPDF works faster if the whole input is given at once but still has acceptable runtimes for line by line input.

Two different ways of general layouting are benchmarked:

L
This version uses the low-level layouting facility HexaPDF::Layout::TextLayouter.
C
This version uses the high-level HexaPDF::Composer to construct the document.
Prawn

Homepage: https://prawnpdf.org
Language: Ruby
Version: 2.4.0

Prawn is much faster and uses much less memory if the input is provided line by line. However, it still works if the whole input is provided at once.

ReportLab

Homepage: https://www.reportlab.com/opensource/
Language: Python
Version: 3.5.34

ReportLab also needs its input line by line. Otherwise it is much, much slower (at least 60x, then the test run was aborted).

fpdf2

Homepage: https://pyfpdf.github.io/fpdf2/
Language: Python
Version: 2.5.5

As with HexaPDF itself, fpdf2 works equally fine when getting the input as one big string or line by line.

TCPDF

Homepage: https://tcpdf.org/
Language: PHP
Version: 6.3.5

As with Prawn and ReportLab, TCPDF needs its input line by line. Otherwise it is much, much slower when line wrapping needs to be done (the test run was aborted because it took too long).

Results

These benchmark results are from 2022-12-30.

benchmark graphic

    Time Memory File size
hexapdf L 400 1.091ms 98.312KiB 361.572
hexapdf C 400 1.245ms 93.916KiB 361.581
prawn 400 5.245ms 53.552KiB 526.289
reportlab/C 400 1.871ms 43.652KiB 486.548
fpdf2 400 1.776ms 42.972KiB 435.599
tcpdf 400 1.449ms 32.824KiB 513.780
hexapdf L 200 1.328ms 101.644KiB 408.491
hexapdf C 200 1.428ms 96.700KiB 408.495
prawn 200 7.171ms 56.136KiB 665.500
reportlab/C 200 2.011ms 44.700KiB 584.702
fpdf2 200 2.031ms 47.180KiB 543.669
tcpdf 200 1.721ms 34.368KiB 668.559
hexapdf L 100 1.472ms 106.632KiB 463.814
hexapdf C 100 1.641ms 100.128KiB 463.814
prawn 100 9.590ms 63.112KiB 850.581
reportlab/C 100 2.188ms 44.788KiB 698.375
fpdf2 100 2.438ms 53.656KiB 684.712
tcpdf 100 2.205ms 38.588KiB 918.499
hexapdf L 50 2.159ms 211.244KiB 569.340
hexapdf C 50 2.515ms 202.460KiB 569.334
prawn 50 16.201ms 69.304KiB 1.263.210
reportlab/C 50 2.634ms 44.864KiB 933.885
fpdf2 50 3.185ms 70.516KiB 1.001.034
tcpdf 50 3.200ms 45.308KiB 1.465.888
hexapdf L 400 ttf 1.293ms 104.504KiB 442.425
hexapdf C 400 ttf 1.461ms 99.476KiB 442.442
prawn 400 ttf 5.037ms 54.204KiB 561.033
reportlab/C 400 ttf 2.142ms 47.844KiB 621.389
fpdf2 400 ttf 1.955ms 43.976KiB 527.019
tcpdf 400 ttf 1.730ms 39.264KiB 631.677
hexapdf L 200 ttf 1.412ms 96.992KiB 504.455
hexapdf C 200 ttf 1.540ms 95.580KiB 504.458
prawn 200 ttf 6.718ms 59.500KiB 715.068
reportlab/C 200 ttf 2.277ms 48.436KiB 730.741
fpdf2 200 ttf 2.235ms 48.476KiB 653.382
tcpdf 200 ttf 1.987ms 40.340KiB 818.349
hexapdf L 100 ttf 1.605ms 108.816KiB 606.549
hexapdf C 100 ttf 1.918ms 101.408KiB 606.553
prawn 100 ttf 10.263ms 69.800KiB 1.015.735
reportlab/C 100 ttf 2.513ms 48.564KiB 920.045
fpdf2 100 ttf 2.713ms 59.052KiB 889.109
tcpdf 100 ttf 2.705ms 43.512KiB 1.200.745
hexapdf L 50 ttf 4.070ms 297.268KiB 767.835
hexapdf C 50 ttf 4.418ms 297.396KiB 767.840
prawn 50 ttf 17.560ms 70.156KiB 1.572.099
reportlab/C 50 ttf 3.080ms 48.908KiB 1.249.287
fpdf2 50 ttf 3.698ms 81.044KiB 1.318.127
tcpdf 50 ttf 4.004ms 53.004KiB 1.941.055