[Repo Assist] perf: cache property name/metadata lookups in getPropertyValues#373
Merged
sergey-tihon merged 4 commits intomasterfrom Apr 11, 2026
Conversation
Previously getPropertyValues called GetProperties() and GetCustomAttributes() via reflection on every invocation. These are O(n) per call even for the same type. The existing propCache for formatObject demonstrated the same pattern. Add propNameCache: ConcurrentDictionary<Type, (string * PropertyInfo)[]> that memoises the (serialized-name, PropertyInfo) array for each type on first use. Subsequent calls to getPropertyValues for the same type skip both GetProperties and per-property GetCustomAttributes entirely. This benefits APIs that use form-encoded or multipart bodies (toFormUrlEncodedContent / toMultipartFormDataContent) for clients that make repeated calls with the same model types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Improves request-time performance in SwaggerProvider.Runtime by caching reflection lookups used to extract object properties for form-encoded and multipart request bodies, avoiding repeated property enumeration and JsonPropertyNameAttribute inspection for the same model types.
Changes:
- Added a
ConcurrentDictionary<Type, (string * PropertyInfo)[]>cache for serialized property name +PropertyInfopairs. - Refactored
getPropertyValuesto use the cached(name, PropertyInfo)pairs instead of re-running reflection each call.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
6 tasks
…unwrapping, cache path) Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/7ba4f18b-f8e6-4339-9d3e-6f9b3106efc0 Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com>
Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/e118cf87-3a35-4328-b45d-436ae073a32b Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 This PR was created by Repo Assist, an automated AI assistant.
Background
getPropertyValuesis called at request time for every API call that uses form-encoded or multipart bodies (toFormUrlEncodedContent/toMultipartFormDataContent). On each invocation it previously performed:GetProperties(Public | Instance)— a reflection lookup over the typeGetCustomAttributes(typeof<JsonPropertyNameAttribute>, false)— another reflection lookup to resolve the JSON-serialised nameBoth calls are re-done for every request even when the same model type is used repeatedly.
Fix
Introduce
propNameCache: ConcurrentDictionary<Type, (string * PropertyInfo)[]>that memoises the(serialized-name, PropertyInfo)array for each type on first use. Subsequent calls togetPropertyValuesfor the same type skip bothGetPropertiesand per-propertyGetCustomAttributesentirely.This is consistent with the existing
propCacheused byformatObjectfor the same reason.Changes
src/SwaggerProvider.Runtime/RuntimeHelpers.fspropNameCache+getPropertyNamesAndInfoshelper; refactorgetPropertyValuesto use the cacheTest Status
✅ Build: succeeded (0 errors, pre-existing warnings only)
✅ Unit tests: 316 passed, 0 failed, 2 skipped (same as baseline)
✅ Format check:
fantomasapplied and re-verified cleanIntegration/provider tests require a running Swashbuckle test server and were not run; the change does not touch schema parsing, type compilation, or HTTP dispatch logic.