Skip to main content

Performance

DocStencil is an in-process JVM library. Rendering happens entirely in memory inside your application. There is no server, no queue, and no network round-trip. This page reports measured throughput for representative templates and explains how performance scales.

Headline numbers

ScenarioOutput sizeMedian time per documentThroughput
Minimal template (framework overhead floor)11 KB2.8 ms~350 docs/sec per core
One-page invoice (loops, calculations, date/currency formatting)26 KB6 ms~165 docs/sec per core (~10,000/min)
One-page invoice, rendered concurrently on 16 cores26 KBn/a~1,400 docs/sec (~84,000/min)
Large generated report (3,905 sections, ~19,500 paragraphs, ~11,700 tables)484 KB1.7 s~34 docs/min per core

Measured on an AMD Ryzen 9 9950X (16 cores / 32 threads) running Linux, on Eclipse Temurin JDK 8, the minimum Java version DocStencil supports. Newer JVMs are typically faster.

What one render includes

Every number above covers the full pipeline for a document: reading the DOCX archive, parsing the template expressions, rendering with the provided data, and writing a valid DOCX archive back out. There is no hidden warm cache of compiled templates behind these figures.

Documents per minute from a single template

A template is loaded once (OfficeTemplate.fromBytes) and can then be rendered any number of times with different data. Rendering is CPU-bound and stateless, so throughput scales linearly with cores. It also scales horizontally with application instances, since there is no shared state or external service.

For capacity planning: a typical one-to-few-page business document costs single-digit milliseconds per document per core. A single mid-range 8-core server conservatively renders several hundred such documents per second.

Many different templates

DocStencil has no separate template-compilation step to amortize: template expressions are parsed as part of every render, and that parse is included in all per-document times above. Loading a different template instead of reusing one adds only the cost of reading its ZIP archive, measured at well under 1 ms for the templates above (within measurement noise).

Practically, this means throughput across N distinct templates is the same as rendering N documents from one template. There is no per-template setup penalty to plan around.

Framework overhead vs. template cost

The minimal-template scenario measures DocStencil's fixed overhead: ~2.8 ms to unzip, parse, render, and rezip a document with almost no content. Everything beyond that floor scales with the content volume of your template and data: the number of paragraphs, table rows, and expressions actually produced. A 484 KB report with ~19,500 paragraphs and ~11,700 tables takes about 1.7 seconds; a one-page invoice takes 6 ms.

This is why the most meaningful benchmark is your own template. The benchmark suite is part of the open-source repository and takes one command to run against any template.

Reproducing these numbers

The benchmarks are ordinary tests in the public docstencil-core repository:

./gradlew :docstencil-core:test --tests "*ThroughputBenchmarkTest*"

Results are printed as BENCH | lines in the test output (captured in the Gradle test report). Each scenario runs a JIT warmup phase followed by up to 300 timed iterations and reports mean, median, and p95 times.