Одной из важных частей любой системы управления проектами является возможность сделать отчёт о текущем положении дел. Это позволяет точнее оценивать текущее состояние дел. Для пользователей такой отчёт может быть не только аналитикой нужной для работы, но и своеобразной формой отчётности. Поэтому в компании Revizto уделяют большое внимание технической стороне генерации отчётов.

У отдельных клиентов отчёты представляют из себя большие pdf на десятки тысяч страниц. Само собой такие отчёты весят гигабайты и генерация их занимает продолжительное время. Столкнувшись с очередным ростом размера отчёта, мы решили проанализировать нашу архитектуру генерации pdf.

Традиционно в вебе генерация pdf состоит из двух этапов:

  1. Генерация html страницы, которая потом станет pdf
  2. Перевод html в pdf

Первый этап в нашем случае занимал достаточно мало времени, а вот второй мог длиться больше часа. Поэтому мы сделали небольшое сравнение какие существуют опенсорсные возможности по генерации pdf:

  1. PhantomJs

        Command being timed: "phantomjs --ssl-protocol=any ./capture.js 1.html 1.pdf"
        User time (seconds): 2240.56
        System time (seconds): 6.96
        Percent of CPU this job got: 83%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 44:35.89
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 1821840
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 28
        Minor (reclaiming a frame) page faults: 489364
        Voluntary context switches: 53462
        Involuntary context switches: 31797
        Swaps: 0
        File system inputs: 4576
        File system outputs: 233848
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
  2. Chrome headless

        Command being timed: "/usr/bin/google-chrome-stable --headless --disable-gpu --print-to-pdf 1.html"
        User time (seconds): 54.22
        System time (seconds): 7.32
        Percent of CPU this job got: 5%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 18:49.74
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 951796
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 2
        Minor (reclaiming a frame) page faults: 938614
        Voluntary context switches: 184497
        Involuntary context switches: 37463
        Swaps: 0
        File system inputs: 368
        File system outputs: 174352
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
  3. Wkhtmltopdf
        Command exited with non-zero status 1
        Command being timed: "wkhtmltopdf 1.html 1.pdf"
        User time (seconds): 3356.13
        System time (seconds): 7.12
        Percent of CPU this job got: 99%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 56:21.54
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 3457744
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 8
        Minor (reclaiming a frame) page faults: 977440
        Voluntary context switches: 38567
        Involuntary context switches: 47975
        Swaps: 0
        File system inputs: 1240
        File system outputs: 197480
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 1

Из преведенного теста видно, что лучший результат получается у chrome, потом в два раза хуже phantomJs, а потом ещё значительно хуже Wkhtmltopdf. Этот результат перекликается с проблемами с разработкой phantomJs

C другой стороны chrome зависит от X11, так что на сервере вопросов с ним будет значительно больше чем с phantomJs.

Если делать небольшой вывод, то для тестирования машине с десктопом chrome безусловный победитель. На сервере его разумно использовать, если не бояться поставить туда X11, иначе phantomJs будет оптимальным вариантом