Skip to content

perf(converter): detectOAS32Features allocates a visited map per media type and per component schema #430

Description

@erraggy

detectOAS32SchemaFeatures is called with a freshly allocated make(map[*parser.Schema]bool) at each site — once per media type, once per component schema. On a document with many media types that is one map allocation each, plus a full schema walk.

Measurements

BenchmarkConvertParsedOAS3ToOAS2, allocs/op:

v1.58.0 v1.59.0
Small 209 268
Medium 2208 2924

Attribution, by reverting individual walks:

Source Small Medium
mt.Schema walk (#426) +48 of 59 +109 of 716
Rest of the 3.2 detection walk (#412) +11 +607

Why this is not filed as a regression

converter/oas32_features.go did not exist at v1.58.0 — it was created in #412. Before this release, oastools convert -t 2.0 reported nothing at all about OAS 3.2 fields. The cost buys output that did not previously exist, so there is no like-for-like baseline to regress against. Accepted for v1.59.0 and called out in the release notes.

What is worth fixing is the per-call map allocation, which is incidental rather than inherent.

The catch

Sharing one visited map across schemas is not behavior-preserving. Each call currently gets a fresh set, so a schema reachable from two paths is reported at each path. One shared map would report only the first, silently dropping findings.

So the safe shapes are:

  1. Allocate lazily, on first recursion rather than at the call — most inline schemas never recurse.
  2. Keep per-call sets but pool or reuse the allocation.

Option 1 mirrors what validator/schema_traversal.go does for its callback visited set, though note the measurement there: the equivalent change produced no measurable improvement, because the compiler was already eliding the allocation. Measure before claiming a win here too.

Acceptance

  • BenchmarkConvertParsedOAS3ToOAS2 allocs/op improves measurably, or the finding is closed with the measurement showing why it cannot
  • A schema reachable from two paths is still reported at both

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestperfPerformance

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions