Skip to content

Benchmarks de Performance

Benchmarks de performance reais comparando TCPDF-Next contra três bibliotecas PHP PDF estabelecidas: TCPDF, DomPDF e mPDF. Todos os testes foram executados no mesmo hardware sob condições Docker controladas. Os resultados são medianas de 20 iterações para eliminar ruído de outliers.

Ambiente de Teste

ParâmetroValor
CPUIntel Core i9-13900K (x86-64)
RAM64 GB DDR5 (Docker limitado a 16 GB)
Docker4 CPUs, 16 GB RAM, Debian bookworm
PHP8.5.3 (CLI, OPcache habilitado, JIT habilitado)
TCPDF-Next1.7.0
TCPDF6.10.1
DomPDFv3.1.4
mPDFv8.2.7
Artisan (Chrome)Headless Chromium via CDP
RoadRunnerspiral/roadrunner-http ^3.6 (testes de throughput HTTP)
Warmup3 iterações (descartadas)
Medições20 iterações (mediana reportada)
Cronometragemhrtime(true) relógio de parede com precisão de nanossegundos

Comparação Interativa

▼ Lower is better
TCPDF-Next
0.68 ms
TCPDF
2.55 ms3.7x
DomPDF
4.16 ms6.1x
mPDF
6.71 ms9.9x

PHP 8.5.3 + OPcache + JIT · Docker 4 CPUs / 16 GB · i9-13900K · Median of 20 runs

Velocidade de Geração

Cada cenário foi executado 20 vezes após 3 iterações de warmup. O tempo mediano de geração é reportado.

Documento Simples (1 Página)

Uma única página A4 com um heading e texto formatado básico usando a fonte Helvetica embutida. Sem imagens, sem tabelas.

BibliotecaTempo (ms)
TCPDF-Next0,68
TCPDF2,55
DomPDF4,16
mPDF6,71

O TCPDF-Next completa o cenário mais simples em menos de 1 ms -- 3,8x mais rápido que TCPDF, 6,1x mais rápido que DomPDF e 9,9x mais rápido que mPDF.

Fatura (2 Páginas)

Uma fatura de duas páginas com 25 linhas tabulares de itens, subtotais, cabeçalhos, rodapés e uma imagem de logo.

BibliotecaTempo (ms)
TCPDF1,96
TCPDF-Next2,01
mPDF15,86
DomPDF17,33

TCPDF-Next e TCPDF estão virtualmente empatados no cenário de Fatura (~1,0x). Ambos superam significativamente mPDF (7,9x mais lento) e DomPDF (8,6x mais lento).

Relatório de 100 Páginas

Um documento de 100 páginas com conteúdo misto denso: headings, parágrafos e dados estruturados.

BibliotecaTempo (ms)
TCPDF-Next34,29
TCPDF105,39
mPDF1.106,59*
DomPDF2.129,12

O TCPDF-Next completa um relatório de 100 páginas em 34,29 ms -- 3,1x mais rápido que TCPDF, 32,3x mais rápido que mPDF e 62,1x mais rápido que DomPDF.

Nota de Compatibilidade JIT

*O resultado do mPDF no Relatório de 100 Páginas foi medido com JIT desabilitado (opcache.jit=0) devido a um segfault do PHP JIT (SIGSEGV, código de saída 139) no caminho de código do mPDF. O cache de bytecode do OPcache permaneceu ativo. Esta é uma classe conhecida de bugs do PHP JIT que afeta certos padrões de loop complexos. Todos os outros cenários do mPDF foram executados com JIT habilitado.

Documento TrueType (1 Página)

Uma única página A4 usando DejaVu Sans (~700 KB fonte TrueType). Este cenário expõe os custos reais de parsing de arquivo de fonte -- diferente do Helvetica (fonte Base14 embutida que não requer I/O de arquivo).

BibliotecaTempo (ms)
TCPDF-Next4,08
TCPDF12,11
mPDF16,51
DomPDF24,14

O TCPDF-Next faz o parse e incorpora a fonte TrueType 3,0x mais rápido que TCPDF, 4,0x mais rápido que mPDF e 5,9x mais rápido que DomPDF.

Velocidade Relativa (Todos os Cenários)

Todos os valores relativos ao TCPDF-Next (baseline 1,0x). Menor = mais rápido.

CenárioTCPDF-NextTCPDFDomPDFmPDF
Documento Simples1,0x3,8x6,1x9,9x
Fatura1,0x~1,0x8,6x7,9x
Relatório de 100 Páginas1,0x3,1x62,1x32,3x
Documento TrueType1,0x3,0x5,9x4,0x

HTML para PDF

Abordagens de Processamento HTML

Diferentes bibliotecas adotam abordagens fundamentalmente diferentes para converter HTML em PDF. Entender essas diferenças é essencial para interpretar os resultados do benchmark:

Tradução Direta (TCPDF-Next, TCPDF) -- O parser HTML embutido tokeniza tags HTML e as mapeia diretamente para comandos de desenho PDF (Cell, MultiCell, Image) em um único passo de streaming. Esta abordagem é extremamente rápida, mas suporta apenas tags HTML básicas e CSS inline -- sem Flexbox, sem Grid, sem seletores CSS complexos.

Engine de Layout CSS (DomPDF, mPDF) -- Estas bibliotecas são projetadas com HTML como sua interface primária. O DomPDF constrói uma árvore DOM completa, aplica a cascata CSS (especificidade, herança) e calcula o layout do box-model antes de renderizar em PDF. O WriteHTML() do mPDF similarmente processa HTML através de sua própria engine de layout CSS. Ambos suportam mais recursos CSS do que parsers de tradução direta (floats, elementos posicionados, tabelas estilizadas), mas ainda ficam aquém do CSS3 completo a nível de navegador.

Renderização Completa do Navegador (Artisan / Chrome) -- O TCPDF-NextArtisan delega a renderização ao Chromium headless via Chrome DevTools Protocol (CDP). Isso fornece suporte CSS3 pixel-perfect: Flexbox, Grid, Web Fonts, media queries, variáveis CSS -- saída idêntica ao que um navegador Chrome produziria.

O benchmark compara a abordagem nativa de cada biblioteca: TCPDF-Next e TCPDF usam seu parser de tradução direta embutido; DomPDF e mPDF usam suas engines de renderização CSS (sua API primária); Artisan usa Chrome.

Resultados

BibliotecaAbordagemTempo (ms)
TCPDF-NextTradução direta1,51
TCPDFTradução direta6,60
DomPDFEngine de layout CSS13,69
mPDFEngine de layout CSS29,63
Artisan (Chrome)Renderização completa do navegador66,70

Tempo Relativo (HTML para PDF)

BibliotecaRelativo
TCPDF-Next1,0x
TCPDF4,4x
DomPDF9,0x
mPDF19,6x
Artisan (Chrome)44,1x

O parser de tradução direta do TCPDF-Next entrega performance abaixo de 2 ms -- 4,4x mais rápido que o parser baseado em regex do TCPDF, 9,0x mais rápido que a engine de layout CSS do DomPDF e 19,6x mais rápido que mPDF. O Artisan (Chrome) é 44,1x mais lento, mas fornece fidelidade CSS3 completa que nenhuma outra biblioteca consegue igualar.

Artisan Chrome -- Detalhamento por Fases

Decompõe o pipeline do Artisan (Chrome) em duas fases:

  1. Chrome CDP Render -- Chrome headless converte HTML para bytes PDF via printToPDF
  2. PDF Import + Embed -- TCPDF-Next faz parse do PDF do Chrome, extrai a página como Form XObject e incorpora no documento de destino
FaseMediana (ms)Média (ms)Mín (ms)Máx (ms)Desvpad
Chrome CDP Render81,1781,1765,5195,804,84
PDF Import + Embed1,962,081,602,870,40
Total83,3583,2968,2097,564,70

Distribuição de tempo: Chrome CDP = 97,4% | PDF Import = 2,3%

O printToPDF do Chrome domina o pipeline com 97,4% do tempo total. A fase de PDF Import (PdfReader + PageImporter + embedding do XObject) adiciona apenas ~2 ms -- overhead desprezível.

Medição Padrão vs Por Fases

O teste padrão do Artisan (66,70 ms) usa o método integrado writeHtmlChrome() com BrowserPool keep-alive. O teste por fases (83,35 ms total) instrumenta separadamente cada fase, adicionando overhead de medição. Ambos usam a mesma instância Chrome keep-alive -- o custo de cold-start de ~250 ms para o lançamento inicial do Chromium é excluído, pois é um custo único amortizado em milhares de requisições.

Quando Usar Qual Abordagem

Para HTML simples (tabelas, formatação básica), use o parser HTML embutido do TCPDF-Next (1,51 ms). Para layouts CSS3 complexos que requerem fidelidade pixel-perfect (Flexbox, Grid, Web Fonts), use o Artisan -- o overhead de ~67 ms compra todo o poder da engine de renderização do Chrome.

Ciclo de Vida do Worker (DocumentFactory vs Standalone)

O TCPDF-Next fornece um padrão DocumentFactory projetado para workers PHP de longa duração (RoadRunner, Swoole, Laravel Octane). O factory pré-inicializa e bloqueia registries compartilhados (FontRegistry, ImageRegistry) no tempo de boot. Cada requisição HTTP cria um Document leve e descartável a partir do factory -- eliminando overhead de inicialização por requisição.

Esta seção compara DocumentFactory (registries compartilhados e bloqueados) contra createStandalone() (registries novos por chamada).

Fontes Embutidas (Helvetica)

ModoMediana (ms)Pico de Memória (MB)Tamanho do Arquivo (KB)
DocumentFactory0,604,03,3
createStandalone()0,704,03,3

Resultado: ~equivalente (proporção 0,86x). Com fontes embutidas (Helvetica), ambos os modos têm performance idêntica porque não há parsing de arquivo de fonte para cachear. A vantagem real do DocumentFactory aparece com fontes TrueType.

Fontes TrueType (DejaVu Sans)

Este é o teste-chave para a proposta de valor do DocumentFactory. Diferente do teste Helvetica acima (fonte embutida, zero parsing), este teste usa DejaVu Sans (~700 KB fonte TrueType). O DocumentFactory pré-registra e cacheia dados de fonte parseados no boot -- requisições subsequentes pulam todo I/O de arquivo de fonte. O createStandalone() precisa fazer parse do arquivo .ttf em toda requisição.

ModoMediana (ms)Pico de Memória (MB)Tamanho do Arquivo (KB)
Factory (TTF cacheado)2,606,024,5
Standalone (TTF parse)4,096,024,3

Speedup do Factory: 1,6x -- O parsing de fonte cacheado elimina ~1,5 ms por requisição. Em um worker RoadRunner/Swoole processando 1.000 requisições/minuto, isso economiza ~25 segundos de tempo de CPU por minuto.

Pico de Uso de Memória

Todos os valores em MB (mediana). O benchmark de cada biblioteca roda em seu próprio subprocesso PHP -- apenas o autoloader necessário é carregado, então memory_get_peak_usage() reflete o custo real de memória apenas daquela biblioteca.

Cenários Padrão

CenárioTCPDF-NextTCPDFDomPDFmPDF
Documento Simples4,012,06,014,0
Fatura4,012,012,014,0
Relatório de 100 Páginas4,012,066,027,9*
Documento TrueType6,014,020,016,0

O TCPDF-Next mantém um footprint consistente de 4 MB de documentos de 1 página a 100 páginas, demonstrando gerenciamento eficiente de memória através de objetos de página compactados e referências de recursos compartilhados.

Memória HTML para PDF

BibliotecaPico de Memória (MB)
TCPDF-Next4,0
Artisan (Chrome)4,0
DomPDF10,0
TCPDF12,0
mPDF18,0

O Artisan (Chrome) mede apenas a memória do lado PHP -- o processo Chrome headless tem seu próprio espaço de memória gerenciado pelo SO.

Tamanho do Arquivo de Saída

Todos os valores em KB (mediana).

Cenários Padrão

CenárioTCPDF-NextTCPDFDomPDFmPDF
Documento Simples3,37,11,728,0
Fatura5,09,24,030,2
Relatório de 100 Páginas96,4100,8128,7181,1*
Documento TrueType24,7101,316,142,4

O DomPDF produz os menores arquivos para documentos simples (1,7 KB) através de otimização agressiva de content-stream. O TCPDF-Next produz saída compacta através de cross-reference streams e object streams do PDF 2.0. O TCPDF incorpora um subset de fonte TrueType significativamente maior (101,3 KB vs 24,7 KB).

Tamanho de Arquivo HTML para PDF

BibliotecaTamanho do Arquivo (KB)
DomPDF5,3
TCPDF-Next6,6
TCPDF12,6
Artisan (Chrome)36,9
mPDF46,0

A saída do Artisan (Chrome) é maior (36,9 KB) porque o printToPDF do Chrome gera um PDF standalone completo com recursos incorporados.

Throughput

Testes de throughput rodam continuamente por 30 segundos usando o cenário de documento simples. Os valores refletem a capacidade de geração sustentada sob carga.

Padrão (docs/seg)

ModoTCPDF-NextTCPDFDomPDFmPDF
Thread Única2.6051.169233130
4 Workers9.2214.163841487

Documentos por Minuto

ModoTCPDF-NextTCPDFDomPDFmPDF
Thread Única156.28470.13413.9567.800
4 Workers553.280249.75250.48429.194

Com 4 workers, o TCPDF-Next sustenta mais de 9.200 documentos por segundo -- mais de 553.000 documentos por minuto. Isso é 2,2x o throughput do TCPDF, 11,0x do DomPDF e 19,0x do mPDF.

Throughput por Ciclo de Vida do Worker

Compara throughput de DocumentFactory vs createStandalone() usando fonte Helvetica embutida.

ModoDocumentFactorycreateStandalone()
Thread Única2.4902.515
4 Workers9.0749.191

Com fontes embutidas, DocumentFactory e createStandalone() produzem throughput equivalente -- sem parsing de fonte para cachear.

Throughput de Documento TrueType

Throughput com fontes TrueType (DejaVu Sans) -- expõe o overhead real de parsing de fonte por biblioteca.

BibliotecaThread Única (docs/seg)
TCPDF-Next242
TCPDF81
mPDF50
DomPDF30

O throughput TrueType do TCPDF-Next é 3,0x o do TCPDF, 4,8x o do mPDF e 8,0x o do DomPDF -- refletindo seu subsetting e caching eficientes de fontes.

Throughput TTF por Ciclo de Vida do Worker

DocumentFactory (dados de fonte TrueType cacheados) vs createStandalone() (parse do TTF a cada requisição).

ModoFactory (TTF cacheado)Standalone (TTF parse)
Thread Única364243
4 Workers1.327871

Vantagem de throughput do Factory: 1,5x (thread única). Dados de fonte TrueType cacheados eliminam o overhead de parsing do .ttf por requisição. Com 4 workers, o factory alcança 1.327 docs/seg -- uma melhoria de 52,4% em relação ao standalone.

Throughput HTTP RoadRunner

Benchmark real de servidor HTTP usando RoadRunner com padrão de worker DocumentFactory. Medido via ab (Apache Bench).

ConfigDocs/segLatência Média (ms)p50 (ms)p99 (ms)Falhas
1 worker / 1 concorrente1.3200,76110
4 workers / 4 concorrentes4.8120,83110

Overhead HTTP vs pcntl_fork bruto:

  • Thread única: 49,3% de overhead (1.320 vs 2.605 docs/seg)
  • Multi-worker: 47,8% de overhead (4.812 vs 9.221 docs/seg)

O overhead de ~48% reflete o custo da stack HTTP completa (TCP accept, HTTP parse, response write). Mesmo com esse overhead, o TCPDF-Next atrás do RoadRunner entrega 4.812 respostas HTTP de PDF reais por segundo com latência sub-milissegundo e zero requisições falhadas.

Metodologia

  • Ambiente: Todas as bibliotecas rodam dentro do mesmo container Docker (PHP 8.5.3, Debian bookworm) com configuração idêntica.
  • Restrições de recursos: Container limitado a 4 CPUs e 16 GB de RAM via restrições de recursos Docker.
  • Runtime: OPcache e JIT habilitados para todas as bibliotecas. Avisos de deprecação suprimidos globalmente para cronometragem justa.
  • Isolamento por subprocesso: Cada par biblioteca/cenário roda em um processo PHP separado (exec()) para medição precisa de memória -- classes de autoloader de outras bibliotecas não poluem memory_get_peak_usage().
  • Paridade de API: TCPDF-Next e TCPDF usam API nativa Cell/MultiCell para cenários não-HTML. DomPDF e mPDF usam markup HTML equivalente (sua interface nativa).
  • Teste de fonte TrueType usa DejaVu Sans (~700 KB .ttf) para expor custos reais de parsing de fonte; testes com Helvetica (Base14) mostram baseline de overhead zero.
  • Artisan (Chrome) usa Chromium headless via CDP para renderização CSS3 pixel-perfect (JavaScript desabilitado via CSP).
  • Artisan por fases decompõe a renderização do Chrome: Fase 1 (Chrome CDP printToPDF) vs Fase 2 (PdfReader + PageImporter + embed).
  • Ciclo de vida do worker compara DocumentFactory (FontRegistry compartilhado + lock, ImageRegistry) vs createStandalone() (registries novos por chamada).
  • Ciclo de vida do worker TTF demonstra o valor-chave do DocumentFactory: dados de fonte TrueType cacheados entre milhares de requisições do worker.
  • RoadRunner HTTP usa roadrunner-server/roadrunner com padrão de worker DocumentFactory, medido via ab (Apache Bench).
  • Warmup: 3 iterações são executadas e descartadas antes do início da medição, garantindo que OPcache e JIT estejam totalmente aquecidos.
  • Iterações: 20 iterações medidas por cenário. A mediana é reportada para eliminar ruído de outliers.
  • Throughput: Testes rodam continuamente por 30 segundos.
  • Cronometragem: hrtime(true) fornece medição de relógio de parede com precisão de nanossegundos.
  • Memória: memory_get_peak_usage(true) reporta o pico de memória real (RSS).
  • Tamanho de arquivo: A saída é gravada em disco e medida com filesize().

Notas sobre Interpretação dos Dados

  • Isolamento por subprocesso para memória: O benchmark de latência de cada biblioteca roda em seu próprio subprocesso PHP. Apenas o autoloader necessário é carregado, então memory_get_peak_usage() reflete o custo real de memória apenas daquela biblioteca -- não poluição cumulativa de autoloader de outras bibliotecas.
  • Artisan (Chrome) usa BrowserPool keep-alive: O processo Chrome permanece ativo entre iterações, correspondendo ao comportamento em produção (RoadRunner/Swoole/Octane). O overhead de cold-start (~250 ms para lançamento inicial do Chromium) é excluído -- é um custo único amortizado em milhares de requisições.
  • Gap entre Latência e Throughput: Medições de latência de execução única incluem overhead de gc_collect_cycles(), memory_reset_peak_usage() e hrtime() (~0,3 ms). Testes de throughput rodam em loop apertado sem overhead de medição, então seu tempo por documento (1000/docs_por_seg) é menor que a mediana de execução única. Números de throughput refletem mais precisamente a performance em produção.
  • Helvetica vs TrueType: Helvetica é uma fonte PDF embutida (Base14) que não requer I/O de arquivo. O cenário TrueType usa DejaVu Sans, que requer parsing de arquivos .ttf (~700 KB). A vantagem do FontRegistry cacheado do DocumentFactory só se manifesta com fontes TrueType.
  • Compatibilidade JIT (*): Valores marcados com * foram medidos com JIT desabilitado (opcache.jit=0) devido a um segfault do PHP JIT (SIGSEGV, código de saída 139) no caminho de código daquela biblioteca. O cache de bytecode do OPcache permanece ativo. Esta é uma classe conhecida de bugs do PHP JIT que afeta certos padrões de loop complexos.

Reproduzindo os Benchmarks

A suite de benchmark está incluída no repositório. Para reproduzir estes resultados:

bash
cd benchmark
docker compose up --build

Os resultados são impressos no stdout ao final da execução. A configuração Docker garante um ambiente idêntico independente do SO do host.

Leitura Adicional

Distribuído sob a licença LGPL-3.0-or-later.