OE openextract

Benchmarking (maintainer tool)

scripts/bench.py is a maintainer-facing microbenchmark for openextract’s local hot path — the CPU work that runs around every extraction call. It exists to catch local performance regressions during development. It is not a published performance benchmark, and its numbers are not portable across machines.

How to run

From the repository root, with the uv environment set up (uv sync --dev):

uv run python scripts/bench.py

It needs no API keys and makes no network calls — it stubs dummy provider credentials and mocks the LLM call. Results are printed to stdout and the script exits 0.

For the startup and first-error measurements only:

uv run python scripts/bench.py --startup-only

To compare a base install with the full provider development environment without changing the repository’s normal virtual environment:

uv run --isolated --no-dev --locked python scripts/bench.py --startup-only
uv run python scripts/bench.py --startup-only

What it measures

Most rows report median, p95, and best over n iterations (after a warmup), so both typical and tail cost are visible. Startup rows instead report median, best, and worst over five fresh subprocesses:

What it intentionally does NOT measure

Issue #165 before/after record

Measurements below were captured on 2026-08-03 with CPython 3.12.9 on Apple silicon/macOS 26.5.1. They are medians of fresh subprocess samples in the full provider development environment. The base-install result is recorded separately because environment composition materially affects RSS.

Profile / path Before After Change
Full-provider cold import 262.97 ms / 71.91 MiB 61.21 ms / 41.94 MiB -77% latency / -42% RSS
First model-error classification 672.62 ms / +102.59 MiB 44.58 us / +0.00 MiB >99.99% latency reduction
Base-install cold import not recorded 68.16 ms / 44.77 MiB baseline established

Before the change, classifying one Pydantic AI ModelAPIError imported OpenAI, Anthropic, Google GenAI, Botocore, Cohere, Hugging Face, Groq, Mistral, and gRPC exception modules. After the change, the benchmark reports none: the classifier matches exact module/class signatures already present in the exception’s MRO. Public error types and provider mappings are unchanged.

These results establish investigation budgets for comparable Apple-silicon development runs:

The time and RSS values are diagnostic budgets, not CI assertions or public performance guarantees. The zero-provider-import invariant is deterministic and is enforced by the test suite.

When maintainers should run it

Run it before and after a change that touches the local hot path, and compare the two runs on the same machine:

It is also useful when investigating a reported startup or import-time regression.

How to interpret the output

These measurements are a local diagnostic aid. They are not universal performance guarantees and should not be quoted as openextract’s performance characteristics.

Extraction quality (ExtractBench)

For schema-guided extraction accuracy against LlamaIndex ExtractBench, use scripts/extractbench.py with any pydantic-ai model identifier. That tool calls live models and is not a substitute for this local overhead benchmark.