Skip to content

[Repo Assist] Perf: cache FullName, BaseType and GetInterfaces in TargetTypeDefinition#485

Draft
github-actions[bot] wants to merge 2 commits intomasterfrom
repo-assist/perf-cache-targettype-props-20260321-b76dfcd6be6d4c79
Draft

[Repo Assist] Perf: cache FullName, BaseType and GetInterfaces in TargetTypeDefinition#485
github-actions[bot] wants to merge 2 commits intomasterfrom
repo-assist/perf-cache-targettype-props-20260321-b76dfcd6be6d4c79

Conversation

@github-actions
Copy link
Contributor

🤖 This is an automated PR from Repo Assist, an AI assistant for this repository.

Summary

TargetTypeDefinition.FullName, BaseType, and GetInterfaces() each compute their result from immutable input data (inp.Namespace/inp.Name, inp.Extends, inp.Implements) but were recomputed on every call — allocating new strings/arrays and re-running type resolution each time.

For large type providers with many types (e.g. SwaggerProvider), where the F# compiler queries these properties many times per type during type-checking, this saves repeated allocations and type-resolution work.

Changes

Property Before After
FullName String concatenation every call Cached lazy — computed once, same string returned thereafter
BaseType txILType (type-resolution) every call Cached lazy — resolved once
GetInterfaces() Array.map txILType (allocates new Type[]) every call Cached lazy — resolved and allocated once

All three caches use F# lazy which defaults to LazyThreadSafetyMode.ExecutionAndPublication, so concurrent first-access from multiple F# compiler threads is safe.

This is complementary to PR #471 (which cached member-wrapper arrays) and does not touch the thread-safety areas being addressed by PRs #482/#483.

Test Status

Passed!  - Failed: 0, Passed: 117, Skipped: 0, Total: 117 (net8.0)

All 117 pre-existing tests pass. The netstandard2.0 build target ran OOM on the CI machine (infrastructure issue, not caused by this change — the same issue affects master); the net8.0 build and tests both pass cleanly.

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@d1d884596e62351dd652ae78465885dd32f0dd7d

FullName, BaseType and GetInterfaces() on TargetTypeDefinition are each
computed from immutable input data (inp.Namespace/inp.Name, inp.Extends,
inp.Implements) but were recomputed on every call.

- FullName: allocates a new string on every call via string concatenation
- BaseType: resolves the base type via txILType on every call
- GetInterfaces(): resolves and allocates a new Type[] on every call

For large type providers with many types (e.g. SwaggerProvider), where
these properties are queried many times per type during compilation, this
saves repeated allocations and type-resolution work.

All three are now backed by lazy caches initialised on first access.
F# lazy uses LazyThreadSafetyMode.ExecutionAndPublication by default so
concurrent first-access from multiple compiler threads is safe.

All 117 pre-existing tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants