Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slow PDF generation with PHP+DomPDF

I spent a while dealing with a really slow PDF generation process using DomPDF. After a lot of fiddling and googling, I eventually got a solution which I thought I'd post in case some of you are dealing with the same issue.

The problem: An e-commerce site I manage has the functionality to allow sellers to download a PDF file with the purchase orders they have fullfilled (basically a copy of the purchase confirmation shown to the buyer). That has always worked OK. The problem started when I deployed an additional functionality to allow sellers to download a single PDF file with all purchase orders generated between a user-defined set of dates. When the amount of purchase orders that needed to be exported as a single PDF (one per page) went over 20-30, the process became desperatingly slow (as in 30-60 seconds).

Getting the data from the database and parsing it was not an issue. Building the view that was later exported into the PDF wasn't the issue either (outputting the HTML to the screen took a fraction of a second even for hundreds of orders), so I was basically sure that dompdf was the issue.

The setup was as follows: 1.- MySQL database 2.- App server: multiple load-balanced PHP+Nginx+PHP-fpm instances running linux 3.- PHP 7.2 4.- dompdf 0.82 (the latest one) 5.- Codeigniter 3.0.9 6.- Bootstrap for formatting the layout

The goal was to allow downloading multiple (potentially hundreds) of purchase orders in a single PDF in an acceptable time.

like image 849
Javier Larroulet Avatar asked Feb 19 '19 14:02

Javier Larroulet


1 Answers

SOLUTION:

After a lot of googling, trial and error, looking up a lot on Stackoverflow (none of the articles I found were really helpful), I figured out that it was bootstrap that was causing the issue.

I was using bootstrap for very basic layout management and I realized that linking the whole library (even the minified one) into the view that was sent to dompdf was overkill, but I didn't want to re-write the view file.

So, I took a different approach: Get the CSS definitions for the specific classes (6, maybe 7) my view was using and inline them in a <style> tag in the view

<style>
.row {
  margin-right: -15px;
  margin-left: -15px;
}
.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
  position: relative;
  min-height: 1px;
  padding-right: 15px;
  padding-left: 15px;
}

.col-lg-12 {
    width: 100%;
}

.text-center {
  text-align: center;
}

body {
  font-family: Helvetica, Arial, sans-serif;
  font-size: 12px;
  line-height: 1.42857143;
  color: #333;
  background-color: #fff;
}
(...) the list goes on a little longer for some other bootstrap styles and other site-specific ones made by yours truly.
</style>

and remove bootstrap altogether from the view.

retesting, the results were astonishing: A 100 purchase order (100-page) PDF (less than 60 kB in size) which took between 30-60 seconds to be generated and streamed to the user before the change, is now being generated in less than half a second, which confirmed that linking bootstrap produces a HUGE overhead on dompdf which is probably unnecesary in 99% of use cases.

Hope this helps someone. It took quite a few days of work to figure this out.

like image 89
Javier Larroulet Avatar answered Nov 13 '22 13:11

Javier Larroulet