Benchmark hiệu năng
Benchmark hiệu năng thực tế so sánh TCPDF-Next với ba thư viện PDF PHP phổ biến: TCPDF, DomPDF và mPDF. Mọi test được thực hiện trên phần cứng giống nhau dưới điều kiện Docker kiểm soát. Kết quả là trung vị của 20 lần lặp để loại bỏ nhiễu outlier.
Môi trường test
| Tham số | Giá trị |
|---|---|
| CPU | Intel Core i9-13900K (x86-64) |
| RAM | 64 GB DDR5 (Docker giới hạn 16 GB) |
| Docker | 4 CPU, 16 GB RAM, Debian bookworm |
| PHP | 8.5.3 (CLI, OPcache bật, JIT bật) |
| TCPDF-Next | 1.7.0 |
| TCPDF | 6.10.1 |
| DomPDF | v3.1.4 |
| mPDF | v8.2.7 |
| Artisan (Chrome) | Headless Chromium qua CDP |
| RoadRunner | spiral/roadrunner-http ^3.6 (test HTTP throughput) |
| Warmup | 3 lần lặp (bỏ qua) |
| Đo lường | 20 lần lặp (báo cáo trung vị) |
| Đo thời gian | hrtime(true) độ chính xác nanosecond |
So sánh tương tác
PHP 8.5.3 + OPcache + JIT · Docker 4 CPUs / 16 GB · i9-13900K · Median of 20 runs
Tốc độ tạo
Mỗi kịch bản chạy 20 lần sau 3 lần warmup. Thời gian tạo trung vị được báo cáo.
Document đơn giản (1 trang)
Một trang A4 với heading và văn bản định dạng cơ bản dùng font Helvetica tích hợp. Không ảnh, không bảng.
| Thư viện | Thời gian (ms) |
|---|---|
| TCPDF-Next | 0.68 |
| TCPDF | 2.55 |
| DomPDF | 4.16 |
| mPDF | 6.71 |
TCPDF-Next hoàn thành kịch bản đơn giản nhất dưới 1 ms — nhanh hơn 3.8x so với TCPDF, 6.1x so với DomPDF, và 9.9x so với mPDF.
Hóa đơn (2 trang)
Hóa đơn hai trang với 25 hàng mục, tổng phụ, header, footer và ảnh logo.
| Thư viện | Thời gian (ms) |
|---|---|
| TCPDF | 1.96 |
| TCPDF-Next | 2.01 |
| mPDF | 15.86 |
| DomPDF | 17.33 |
TCPDF-Next và TCPDF gần như ngang nhau trong kịch bản hóa đơn (~1.0x). Cả hai vượt trội mPDF (chậm hơn 7.9x) và DomPDF (chậm hơn 8.6x).
Report 100 trang
Document 100 trang với nội dung hỗn hợp dày đặc: heading, đoạn văn và dữ liệu cấu trúc.
| Thư viện | Thời gian (ms) |
|---|---|
| TCPDF-Next | 34.29 |
| TCPDF | 105.39 |
| mPDF | 1,106.59* |
| DomPDF | 2,129.12 |
TCPDF-Next hoàn thành report 100 trang trong 34.29 ms — nhanh hơn 3.1x so với TCPDF, 32.3x so với mPDF, và 62.1x so với DomPDF.
Ghi chú tương thích JIT
*Kết quả Report 100 trang của mPDF được đo với JIT tắt (opcache.jit=0) do PHP JIT segfault (SIGSEGV, exit code 139) trong code path của mPDF. OPcache bytecode caching vẫn hoạt động. Đây là lớp bug PHP JIT đã biết ảnh hưởng đến một số pattern vòng lặp phức tạp. Mọi kịch bản mPDF khác chạy với JIT bật.
Document TrueType (1 trang)
Một trang A4 dùng DejaVu Sans (~700 KB font TrueType). Kịch bản này phơi bày chi phí phân tích file font thực — khác Helvetica (font Base14 tích hợp không cần file I/O).
| Thư viện | Thời gian (ms) |
|---|---|
| TCPDF-Next | 4.08 |
| TCPDF | 12.11 |
| mPDF | 16.51 |
| DomPDF | 24.14 |
TCPDF-Next phân tích và nhúng font TrueType nhanh hơn 3.0x so với TCPDF, 4.0x so với mPDF, và 5.9x so với DomPDF.
Tốc độ tương đối (mọi kịch bản)
Mọi giá trị tương đối với TCPDF-Next (baseline 1.0x). Thấp hơn = nhanh hơn.
| Kịch bản | TCPDF-Next | TCPDF | DomPDF | mPDF |
|---|---|---|---|---|
| Document đơn giản | 1.0x | 3.8x | 6.1x | 9.9x |
| Hóa đơn | 1.0x | ~1.0x | 8.6x | 7.9x |
| Report 100 trang | 1.0x | 3.1x | 62.1x | 32.3x |
| Document TrueType | 1.0x | 3.0x | 5.9x | 4.0x |
HTML sang PDF
Cách tiếp cận xử lý HTML
Các thư viện khác nhau có cách tiếp cận khác nhau cơ bản để chuyển HTML sang PDF. Hiểu các khác biệt này rất quan trọng để diễn giải kết quả benchmark:
Dịch trực tiếp (TCPDF-Next, TCPDF) — Parser HTML tích hợp tokenize tag HTML và ánh xạ trực tiếp sang lệnh vẽ PDF (Cell, MultiCell, Image) trong một lượt streaming. Cách tiếp cận này cực nhanh nhưng chỉ hỗ trợ tag HTML cơ bản và inline CSS — không Flexbox, không Grid, không CSS selector phức tạp.
Engine layout CSS (DomPDF, mPDF) — Các thư viện này được thiết kế với HTML là giao diện chính. DomPDF xây dựng DOM tree đầy đủ, áp dụng CSS cascade (specificity, inheritance), và tính toán box-model layout trước khi render sang PDF. WriteHTML() của mPDF cũng xử lý HTML qua engine layout CSS riêng. Cả hai hỗ trợ nhiều tính năng CSS hơn parser dịch trực tiếp nhưng vẫn thiếu CSS3 cấp trình duyệt đầy đủ.
Render trình duyệt đầy đủ (Artisan / Chrome) — TCPDF-Next Artisan ủy quyền render cho headless Chromium qua Chrome DevTools Protocol (CDP). Điều này cung cấp hỗ trợ CSS3 pixel-perfect: Flexbox, Grid, Web Font, media query, CSS variable — output giống hệt trình duyệt Chrome.
Kết quả
| Thư viện | Cách tiếp cận | Thời gian (ms) |
|---|---|---|
| TCPDF-Next | Dịch trực tiếp | 1.51 |
| TCPDF | Dịch trực tiếp | 6.60 |
| DomPDF | Engine layout CSS | 13.69 |
| mPDF | Engine layout CSS | 29.63 |
| Artisan (Chrome) | Render trình duyệt đầy đủ | 66.70 |
Thời gian tương đối (HTML sang PDF)
| Thư viện | Tương đối |
|---|---|
| TCPDF-Next | 1.0x |
| TCPDF | 4.4x |
| DomPDF | 9.0x |
| mPDF | 19.6x |
| Artisan (Chrome) | 44.1x |
Parser dịch trực tiếp của TCPDF-Next đạt hiệu năng dưới 2 ms — nhanh hơn 4.4x so với parser regex của TCPDF, 9.0x so với engine layout CSS của DomPDF, và 19.6x so với mPDF. Artisan (Chrome) chậm hơn 44.1x nhưng cung cấp độ chính xác CSS3 đầy đủ mà không thư viện nào khác sánh được.
Khi nào dùng cách tiếp cận nào
Cho HTML đơn giản (bảng, định dạng cơ bản), dùng parser HTML tích hợp của TCPDF-Next (1.51 ms). Cho layout CSS3 phức tạp cần pixel-perfect (Flexbox, Grid, Web Font), dùng Artisan — overhead ~67 ms mua được toàn bộ sức mạnh engine render Chrome.
Worker Lifecycle (DocumentFactory vs Standalone)
TCPDF-Next cung cấp pattern DocumentFactory thiết kế cho PHP worker chạy dài (RoadRunner, Swoole, Laravel Octane). Factory khởi tạo trước và khóa registry chia sẻ (FontRegistry, ImageRegistry) lúc boot. Mỗi HTTP request tạo Document nhẹ, dùng xong bỏ từ factory — loại bỏ overhead khởi tạo mỗi request.
Font tích hợp (Helvetica)
| Chế độ | Trung vị (ms) | Bộ nhớ đỉnh (MB) | Kích thước file (KB) |
|---|---|---|---|
| DocumentFactory | 0.60 | 4.0 | 3.3 |
| createStandalone() | 0.70 | 4.0 | 3.3 |
Kết quả: ~tương đương (tỷ lệ 0.86x). Với font tích hợp, cả hai chế độ hoạt động giống nhau vì không có phân tích file font để cache.
Font TrueType (DejaVu Sans)
| Chế độ | Trung vị (ms) | Bộ nhớ đỉnh (MB) | Kích thước file (KB) |
|---|---|---|---|
| Factory (TTF cached) | 2.60 | 6.0 | 24.5 |
| Standalone (TTF parse) | 4.09 | 6.0 | 24.3 |
Factory nhanh hơn: 1.6x — Font parsing cached loại bỏ ~1.5 ms mỗi request.
Bộ nhớ đỉnh
Mọi giá trị tính bằng MB (trung vị).
Kịch bản chuẩn
| Kịch bản | TCPDF-Next | TCPDF | DomPDF | mPDF |
|---|---|---|---|---|
| Document đơn giản | 4.0 | 12.0 | 6.0 | 14.0 |
| Hóa đơn | 4.0 | 12.0 | 12.0 | 14.0 |
| Report 100 trang | 4.0 | 12.0 | 66.0 | 27.9* |
| Document TrueType | 6.0 | 14.0 | 20.0 | 16.0 |
TCPDF-Next duy trì footprint ổn định 4 MB từ document 1 trang đến 100 trang.
Kích thước file output
Mọi giá trị tính bằng KB (trung vị).
Kịch bản chuẩn
| Kịch bản | TCPDF-Next | TCPDF | DomPDF | mPDF |
|---|---|---|---|---|
| Document đơn giản | 3.3 | 7.1 | 1.7 | 28.0 |
| Hóa đơn | 5.0 | 9.2 | 4.0 | 30.2 |
| Report 100 trang | 96.4 | 100.8 | 128.7 | 181.1* |
| Document TrueType | 24.7 | 101.3 | 16.1 | 42.4 |
Throughput
Test throughput chạy liên tục 30 giây dùng kịch bản document đơn giản.
Chuẩn (doc/giây)
| Chế độ | TCPDF-Next | TCPDF | DomPDF | mPDF |
|---|---|---|---|---|
| Đơn luồng | 2,605 | 1,169 | 233 | 130 |
| 4 Worker | 9,221 | 4,163 | 841 | 487 |
Document mỗi phút
| Chế độ | TCPDF-Next | TCPDF | DomPDF | mPDF |
|---|---|---|---|---|
| Đơn luồng | 156,284 | 70,134 | 13,956 | 7,800 |
| 4 Worker | 553,280 | 249,752 | 50,484 | 29,194 |
Với 4 worker, TCPDF-Next duy trì hơn 9,200 document mỗi giây — hơn 553,000 document mỗi phút.
RoadRunner HTTP Throughput
Benchmark HTTP server thực dùng RoadRunner với pattern worker DocumentFactory.
| Cấu hình | Doc/giây | Latency trung bình (ms) | p50 (ms) | p99 (ms) | Thất bại |
|---|---|---|---|---|---|
| 1 worker / 1 concurrent | 1,320 | 0.76 | 1 | 1 | 0 |
| 4 worker / 4 concurrent | 4,812 | 0.83 | 1 | 1 | 0 |
TCPDF-Next sau RoadRunner giao 4,812 HTTP PDF response thực mỗi giây với latency dưới millisecond và không request thất bại.
Phương pháp
- Môi trường: Mọi thư viện chạy trong cùng Docker container (PHP 8.5.3, Debian bookworm) với cấu hình giống nhau.
- Giới hạn tài nguyên: Container giới hạn 4 CPU và 16 GB RAM qua Docker resource constraint.
- Runtime: OPcache và JIT bật cho mọi thư viện.
- Cách ly subprocess: Mỗi cặp thư viện/kịch bản chạy trong PHP process riêng (
exec()) cho đo bộ nhớ chính xác. - Warmup: 3 lần lặp được thực hiện và bỏ trước khi bắt đầu đo.
- Lần lặp: 20 lần đo mỗi kịch bản. Trung vị được báo cáo.
- Throughput: Test chạy liên tục 30 giây.
- Đo thời gian:
hrtime(true)cung cấp đo wall-clock độ chính xác nanosecond.
Tái tạo benchmark
Bộ benchmark được bao gồm trong repository. Để tái tạo kết quả:
cd benchmark
docker compose up --buildĐọc thêm
- Migration từ TCPDF — Hướng dẫn migration từng bước
- Tối ưu hiệu năng — Chế độ streaming, tối ưu bộ nhớ và chiến lược cache