The Python PDF generation library reportlab contains a demo/benchmarking application that takes the Project Gutenberg text of Homer's Odyssey and creates a PDF version from it. This text contains 10.437 lines and about 611.000 characters.
The PDF is generated by simply showing each line of the source text, without wrapping or any other advanced text facilities, once using the built-in standard PDF fonts and once using a TrueType font, creating PDF documents with 232 pages.
This is a nice test of raw text output performance and, as noted above, doesn't need any advanced text layout facilities.
In addition to reportlab I have ported the code to Ruby's Prawn, Perl's PDF::API2 and PHP's TCPDF libraries, to have a broader comparison. Note that reportlab has a module implemented in C that replaces various CPU intensive methods. There is an extra entry for that version of reportlab.
The file script.sh
is a small wrapper script that calls the binaries and records runtime, memory use and the size of the created file. Here are the results using ruby 2.4.2p198 (if you use Ruby 2.3 you will get worse results, for both time and memory):
|-----------------------------------------------------------------|
| | Time | Memory | File size |
|-----------------------------------------------------------------|
| hexapdf 1x | 617ms | 22,468KiB | 395,530 |
| prawn 1x | 570ms | 19,232KiB | 537,468 |
| reportlab 1x | 446ms | 21,320KiB | 413,116 |
| reportlab/C 1x | 351ms | 23,908KiB | 413,116 |
| tcpdf 1x | 970ms | 33,016KiB | 546,968 |
| PDF::API2 1x | 954ms | 28,256KiB | 402,794 |
|-----------------------------------------------------------------|
| hexapdf 5x | 2,517ms | 36,912KiB | 1,973,094 |
| prawn 5x | 2,361ms | 37,200KiB | 2,688,812 |
| reportlab 5x | 2,014ms | 42,376KiB | 2,064,824 |
| reportlab/C 5x | 1,359ms | 40,028KiB | 2,064,824 |
| tcpdf 5x | 5,104ms | 44,032KiB | 2,714,482 |
| PDF::API2 5x | 5,088ms | 41,060KiB | 2,001,755 |
|-----------------------------------------------------------------|
| hexapdf 10x | 5,209ms | 58,608KiB | 3,945,926 |
| prawn 10x | 4,793ms | 57,188KiB | 5,378,100 |
| reportlab 10x | 4,327ms | 67,648KiB | 4,130,218 |
| reportlab/C 10x | 2,822ms | 59,400KiB | 4,130,218 |
| tcpdf 10x | 9,665ms | 60,348KiB | 5,424,797 |
| PDF::API2 10x | 11,878ms | 56,552KiB | 4,001,642 |
|-----------------------------------------------------------------|
| hexapdf 1x ttf | 781ms | 21,848KiB | 476,902 |
| prawn 1x ttf | 1,386ms | 22,696KiB | 554,823 |
| reportlab 1x ttf | 785ms | 27,240KiB | 543,167 |
| reportlab/C 1x ttf | 663ms | 28,220KiB | 543,167 |
| tcpdf 1x ttf | 1,316ms | 33,548KiB | 666,954 |
| PDF::API2 1x ttf | 9,524ms | 48,504KiB | 588,768 |
|-----------------------------------------------------------------|
| hexapdf 5x ttf | 2,890ms | 37,096KiB | 2,333,185 |
| prawn 5x ttf | 6,078ms | 37,696KiB | 2,702,110 |
| reportlab 5x ttf | 4,381ms | 54,352KiB | 2,644,870 |
| reportlab/C 5x ttf | 4,126ms | 50,800KiB | 2,644,870 |
| tcpdf 5x ttf | 5,876ms | 51,064KiB | 3,120,326 |
| PDF::API2 5x ttf | 43,102ms | 69,460KiB | 2,694,564 |
|-----------------------------------------------------------------|
| hexapdf 10x ttf | 5,905ms | 66,192KiB | 4,654,309 |
| prawn 10x ttf | 11,875ms | 62,132KiB | 5,386,301 |
| reportlab 10x ttf | 6,536ms | 87,668KiB | 5,272,797 |
| reportlab/C 10x ttf | 5,078ms | 79,088KiB | 5,272,797 |
| tcpdf 10x ttf | 12,357ms | 70,672KiB | 6,188,591 |
| PDF::API2 10x ttf | 88,427ms | 96,004KiB | 5,327,987 |
|-----------------------------------------------------------------|
Some comments on the results:
- Memory usage is quite the same for all test scripts, with Prawn and HexaPDF consuming the least amount of memory most of the time.
- HexaPDF produces the smallest files out of the box (no version has compression enabled).
- Comparing Prawn with HexaPDF performance-wise, Prawn is faster with the built-in fonts while HexaPDF is way faster with TrueType fonts. The C-backed implementation of reportlab is, naturally, the fastest, especially when using the built-in fonts.