-
Notifications
You must be signed in to change notification settings - Fork 38
Cache Reference Schema #193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cache Reference Schema #193
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #193 +/- ##
==========================================
+ Coverage 97.21% 97.32% +0.11%
==========================================
Files 42 42
Lines 4597 3740 -857
==========================================
- Hits 4469 3640 -829
+ Misses 128 100 -28
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR optimizes validation error path performance by caching the string conversion of rendered schemas. Previously, []byte to string conversions occurred repeatedly inside error loops, causing significant memory allocations (e.g., 504MB per operation in benchmarks). The optimization converts the schema once and stores it in the cache, reducing memory usage by 96.7% and improving latency by 59%.
Key Changes:
- Added
ReferenceSchema stringfield toSchemaCacheEntryto cache the pre-converted string - Modified request/response validation to convert
renderedSchemaonce and reuse across all validation errors - Updated cache warming logic to populate the new field
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| cache/cache.go | Added ReferenceSchema field to cache struct for storing pre-converted string |
| requests/validate_request.go | Updated to use cached ReferenceSchema string instead of repeated string(renderedSchema) conversions |
| responses/validate_response.go | Updated to use cached ReferenceSchema string instead of repeated string(renderedSchema) conversions |
| validator.go | Modified cache warming functions to populate ReferenceSchema field during schema compilation |
| validator_test.go | Added assertions to verify ReferenceSchema is properly cached and matches RenderedInline |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
daveshanley
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Optimize error path performance by caching ReferenceSchema string conversion
Summary
This PR significantly improves validation performance for the error path by eliminating redundant
[]bytetostringconversions of the rendered schema. The optimization caches the string representation and reuses it across all validation errors, leveraging Go's string immutability guarantees.Problem
When validating requests/responses against large OpenAPI schemas, validation errors include the full rendered schema in each
SchemaValidationFailureobject for debugging purposes. Previously, the code convertedrenderedSchema(a[]byte) to a string inside the error processing loop, causing the large byte slice to be copied for every single validation error.For endpoints with complex schemas (e.g., schemas that inline many references and result in 500KB+ rendered schemas), this caused severe performance degradation:
Solution
The fix is simple and leverages Go's string immutability:
renderedSchemato a string immediately after rendering (or loading from cache), before the error loopReferenceSchema stringfield toSchemaCacheEntryto cache the pre-converted stringPerformance Results
Benchmark comparison using a 536KB rendered schema with 100 invalid items:
Before Optimization
After Optimization
Improvement
Valid Path (No Regression)
Valid request performance remains unchanged (differences within measurement noise):
Changes Made
1. Enhanced Cache Structure
2. Request Validation (
requests/validate_request.go)referenceSchemafrom cache (zero conversion cost)renderedSchemato string immediately afterRenderInline()and cache itreferenceSchemavariable instead of callingstring(renderedSchema)repeatedly3. Response Validation (
responses/validate_response.go)Why This Works
Go strings are immutable and use copy-on-write semantics with shared backing storage:
struct { Data uintptr; Len int }= 16 bytesstr2 = str1), only the 16-byte header is copiedMemory impact for 1,000 validation errors:
This is guaranteed safe because strings are immutable in Go - the shared buffer can never be modified.
Testing
Breaking Changes
None. This is a pure performance optimization with no API changes.
Related Issues
This optimization is particularly beneficial for:
oneOf/anyOfschemas that may generate many validation errors