Performance Engineering
Performance Engineering
The large-document milestone was not only a benchmark exercise. It changed the runtime architecture and added repeatable correctness, cleanup and memory diagnostics.
Executive outcome
- paginated Canvas documents can render page by page instead of one giant document-height canvas
- 50-page and 100-page Canvas exports are verified as real, non-empty PDFs on the incremental path
- static HTML footer content is rasterized once and reused across pages
- selectable-text mode caches repeated image sources within one generation
- long work can be cancelled and then safely regenerated
- progress can expose
stage,progress,currentPageandtotalPages - temporary DOM, Canvas backing stores and encoded image references are released earlier
- browser yielding was added between expensive chunks
- encrypted raster memory retention was isolated and reproduced directly in jsPDF
Phase map
| Phase | Focus | Result |
|---|---|---|
| Phase 1 | Benchmark/stress foundation | Actual page count, Blob size, Canvas geometry, timing, memory and progress telemetry. |
| Phase 2.1 | Static HTML footer bottleneck | Render once + reuse; major time, output-size and heap reductions in the fixture. |
| Phase 2.2 | Clean memory isolation | Fresh-context methodology separated temporary peaks from retained heap. |
| Phase 2.3A | Security isolation | Basic user-password encryption identified as the trigger for high raster retention. |
| Phase 2.3B | Large-PDF correctness | Page count alone was proven insufficient; Blob size and Canvas telemetry were added. |
| Phase 2.4 | Scaling and cliff diagnostics | Raster payload + jsPDF encryption pattern isolated; legacy long-canvas failure instrumented. |
| Phase 3.1 | Incremental Canvas | Page-bounded captures replaced the giant capture for paginated Canvas documents. |
| Phase 3.2 | Security re-test | Giant-canvas issue addressed; encrypted-raster retention remained dependency-level. |
| Phase 3.2.1 | Raw jsPDF reproduction | Strongest retention pattern reproduced without Vue component lifecycle. |
| Phase 3.3 | Cancellation + progress | Cooperative cancellation, recovery and current-page progress added. |
| Phase 3.4 | Repeated assets + cleanup | Per-generation image cache and shorter DOM/Canvas lifetimes. |
| Phase 3.5 | Routing regression hardening | Correct incremental Canvas branch restored and protected by 50/100-page E2E tests. |
Headline measured results
| Metric | Before | After | Improvement |
|---|---|---|---|
| HTML footer, no logo | 7.82 s | 1.43 s | ~81.7% less time / 5.47× faster |
| HTML footer + logo | 11.81 s | 1.29 s | ~89.1% less time / 9.16× faster |
| Footer-heavy PDF | ~46.7 MB | ~1.0 MB | ~97.9% smaller |
| No-logo peak heap | 102.6 MB | 26.5 MB | ~74.2% lower |
| Giant Canvas capture geometry | ~99.96M px | ~1.74M px/page | ~98.26% lower peak capture area |
These percentages describe specific benchmark fixtures or capture geometry; they are not universal whole-package speed or memory guarantees.
Current incremental Canvas correctness
| Requested pages | Actual pages | Time | PDF size | Largest encoded Canvas |
|---|---|---|---|---|
| 10 | 10 | 1.53 s | 1.5 MB | 1191 × 1461 |
| 25 | 25 | 4.33 s | 3.9 MB | 1191 × 1461 |
| 40 | 40 | 7.54 s | 6.2 MB | 1191 × 1461 |
| 50 | 50 | 9.68 s | 7.8 MB | 1191 × 1461 |
| 60 | 60 | 12.56 s | 9.3 MB | 1191 × 1461 |
| 75 | 75 | 16.87 s | 11.7 MB | 1191 × 1461 |
| 100 | 100 | 25.25 s | 15.8 MB | 1191 × 1461 |
The maximum encoded Canvas remained page-sized as the requested page count increased.
Encrypted raster PDFs
The strongest high-retention behavior was reproduced with raw jsPDF, so the project documents it as memory retention rather than mislabeling it as a permanent Vue memory leak.
Upstream issue: jsPDF #4017 - encrypted raster PDF memory retention
For large text-heavy secured documents whose CSS is supported by the vector renderer, selectable-text mode can be much lighter than raster Canvas mode. This is workload-dependent, not a universal renderer benchmark.
Verification mindset
Large exports are checked with more than “the Promise resolved”: actual page count, Blob size, Canvas dimensions, cancellation/recovery and cleanup signals are part of the regression strategy.
