Skip to content

Performance

benchmarks/bench.py generates OpenAPI 3.1 specs of growing size, with shared components, nested $refs, 3.1-style nullables, enums and a recursive component, then times normalize and a full diff (both sides normalized) against a copy with a handful of edits.

python benchmarks/bench.py                       # 100, 300 and 1000 operations
python benchmarks/bench.py --ops 2000 --repeat 5

Results on an Apple-silicon laptop, Python 3.12, median of 3 runs. Peak memory is for one diff, measured in a separate run with tracemalloc:

Operations Components normalize (s) diff incl. normalize (s) Peak MiB
101 26 1.6 4.3 35
301 76 2.4 5.1 104
1001 251 3.0 15.3 463

Loading the app (importing it and generating its schema) is not included; for most projects that dominates.

What keeps it bounded

  • Components are inlined, so a rename of a component isn't a change. A component referenced more than 200 times, or nested more than 40 references deep, is stored once in the snapshot instead (like a recursive one), which keeps the snapshot and the diff from growing exponentially on heavily shared schemas.
  • Recursive components are stored once and compared by name.

If a check is slow, run it with -v to see where the time goes (loading, normalizing, diffing, reporting), and open an issue with those timings.