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.6.12

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.7.4

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.6.2

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 2023-08-03.

benchmark graphic

    Time Memory File size
hexapdf L 400 872ms 100.132KiB 361.571
hexapdf C 400 915ms 93.360KiB 361.577
prawn 400 3.659ms 53.820KiB 526.289
reportlab/C 400 1.024ms 44.376KiB 486.548
fpdf2 400 1.528ms 65.940KiB 436.467
tcpdf 400 1.013ms 33.880KiB 513.780
hexapdf L 200 942ms 105.456KiB 408.488
hexapdf C 200 968ms 96.236KiB 408.487
prawn 200 4.846ms 56.428KiB 665.500
reportlab/C 200 1.109ms 44.816KiB 584.702
fpdf2 200 1.722ms 69.776KiB 545.185
tcpdf 200 1.147ms 35.412KiB 668.559
hexapdf L 100 1.066ms 109.812KiB 463.815
hexapdf C 100 1.116ms 100.768KiB 463.809
prawn 100 6.517ms 63.120KiB 850.581
reportlab/C 100 1.220ms 45.656KiB 698.375
fpdf2 100 2.048ms 75.656KiB 687.194
tcpdf 100 1.443ms 38.232KiB 918.499
hexapdf L 50 1.676ms 206.016KiB 569.338
hexapdf C 50 1.649ms 212.212KiB 569.338
prawn 50 11.087ms 69.352KiB 1.263.210
reportlab/C 50 1.413ms 47.328KiB 933.885
fpdf2 50 2.615ms 91.016KiB 1.006.761
tcpdf 50 2.132ms 46.164KiB 1.465.888
hexapdf L 400 ttf 967ms 105.736KiB 442.425
hexapdf C 400 ttf 1.007ms 101.760KiB 442.438
prawn 400 ttf 3.459ms 54.048KiB 561.034
reportlab/C 400 ttf 1.112ms 48.944KiB 621.389
fpdf2 400 ttf 1.770ms 67.216KiB 523.438
tcpdf 400 ttf 1.228ms 39.252KiB 631.677
hexapdf L 200 ttf 1.002ms 98.456KiB 504.454
hexapdf C 200 ttf 1.015ms 98.560KiB 504.454
prawn 200 ttf 4.560ms 59.592KiB 715.069
reportlab/C 200 ttf 1.193ms 49.928KiB 730.741
fpdf2 200 ttf 1.956ms 71.116KiB 650.491
tcpdf 200 ttf 1.325ms 41.348KiB 818.349
hexapdf L 100 ttf 1.173ms 111.944KiB 606.547
hexapdf C 100 ttf 1.200ms 104.832KiB 606.543
prawn 100 ttf 6.907ms 69.844KiB 1.015.736
reportlab/C 100 ttf 1.342ms 50.880KiB 920.045
fpdf2 100 ttf 2.373ms 80.680KiB 888.224
tcpdf 100 ttf 1.765ms 44.372KiB 1.200.745
hexapdf L 50 ttf 3.044ms 288.980KiB 767.835
hexapdf C 50 ttf 3.116ms 284.808KiB 767.852
prawn 50 ttf 11.155ms 70.432KiB 1.572.100
reportlab/C 50 ttf 1.668ms 52.908KiB 1.249.287
fpdf2 50 ttf 3.310ms 100.632KiB 1.320.952
tcpdf 50 ttf 2.604ms 54.100KiB 1.941.055