Generating PDFs with images way too slow

Dave picture Dave · Sep 16, 2014 · Viewed 7.8k times · Source

A big bottleneck I have at the moment is PDF generation each time someone places an order. It's not a big deal for a single order, but when there are a lot in a short time frame, this process is very slow.

The PDF needs text information, a QR code, a Bar code, a logo, and 1 or more (up to 20+) 1/4-width images.

Current process w/ DOMPDF:

  1. QR code image created w/ PHP and saved as png
  2. Bar code image created and saved as png
  3. DomPDF generates PDF

New thought:

  1. HTML2PDF creates PDF, and uses it's qr and bar code tags to generate the bar codes

That theoretically would take care of the QR and Barcode images, but still, the rest of the images make it too slow.

Doing it this way, without any images other than the (QR and Bar code), the PDF can generate in ~500ms, but as soon as I start adding images, it goes up to 2, 3, 4, 5+ seconds each.


When running tests, and processing ~10k orders (in a few minutes), it was still processing the PDFs around 12 hours later until I just shut it down in frustration.

The PDF is generated in a separate queue process, so the person doesn't have to wait when ordering, but - still... it can't take 5+ hours for them to receive their confirmation PDF during high traffic.


Questions / TLDR:

How can I make my process of creating PDFs with a dynamic qr code, a dynamic bar code, dynamic text, and 1-20 static images (images are same across all PDFs) faster?

Are there other potential things I haven't thought of? Maybe making a template PDF and somehow use PHP to just fill in the dynamic spots?

Answer

bancer picture bancer · Sep 16, 2014

I would strongly advice you to use TCPDF library. It's quite fast and can be easily integrated into CakePHP. You can find a lot of examples of how to include images, barcodes and QR codes into PDF at TCPDF examples page.

To further improve the performance use tips from this page:

  • Install and configure a PHP opcode cacher like XCache;
  • Edit the php.ini file and increase the maximum amount of memory a script may consume (memory_limit);
  • Edit the php.ini file and increase the maximum execution time of each script (max_execution_time);
  • Edit the config/tcpdf_config.php file: manually set the $_SERVER['DOCUMENT_ROOT'], K_PATH_MAIN and K_PATH_URL constants, and remove the automatic calculation part;
  • If you are not using the Thai language, edit the config/tcpdf_config.php file and set the K_THAI_TOPCHARS constant to false;
  • If you do not need extended chars, edit the config/tcpdf_config.php file and set the default fonts to core fonts;
  • If you do not need UTF-8 Unicode, set the $unicode parameter on TCPDF constructor to false and the $encoding parameter to 'ISO-8859-1' or other character map.
  • By default TCPDF enables font subsetting to reduce the size of embedded Unicode TTF fonts, this process, that is very slow and requires a lot of memory, can be turned off using setFontSubsetting(false) method;
  • Use core fonts instead of embedded fonts whenever possible;
  • Avoid using the HTML syntax (writeHTML and writeHTMLCell methods) if not strictly required;
  • Split large HTML blocks in smaller pieces;
  • Avoid using transactions if not strictly required;
  • Restart the webserver after changes.

If that does not improve the performance to the acceptable level you can install your CakePHP application (or just the script that runs the generation of PDFs if it doesn't use CakePHP) on a second server with more available resources and use that server only for PDF generation.