Reduce types loaded on startup significantly - #120459

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load
Oct 14, 2025
Merged

Reduce types loaded on startup significantly#120459
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Oct 7, 2025

Copy link
Copy Markdown
Member

Reduce the number of type loads triggered by complex generic constraints. Experiments show about a 20% reduction in startup time on a proxy of the AWS lambda scenario.

The fixes are:

  1. When a method/type has constraints, do not load the constraint types directly if they are generic interfaces. Instead, do accessibility checking and the constraint validation on the signature of the constraint instead.
  2. When a type is loaded, enhance the special marker type optimization in the interface map to allow Interfaces which require implementation of other interfaces to use the special marker type. Notably, use the special marker type so that if a generic interface's first type parameter is used as all of the generic type parameters of a required interface we use the special marker type to indicate that the type is loaded.
    • This also forces us to have a somewhat more complicated implementation of casting, since the previous model of special marker types could not experience an equivalent interface match
  3. When resolving a default interface method, attempt to avoid loading all the interface types associated with a type. Do so by changing the iteration of interfaces to check to see if the approximate interface could possibly have an implementation
  4. When resolving a static virtual method, attempt to avoid loading all the types of the MethodImpl records. Do so by doing a Method name check before loading the type.

In addition, fix a test so that it still throws when loading an invalid type. This required adding a path which forced the interface type to be loaded.

As part of testing this work, the lack of generic variable type safety checks was noticed in crossgen2, and the following changes were made

  • Add support for doing circularity checks on type and method generic parameters to the TypeValidationChecker in crossgen2
  • Add support for doing variance safety checks to the type loader in crossgen2

And in the runtime

  • Remove the circularity of type variables checks happening in generic method load, as it is redundant
  • Put all of the variance safety checks in the runtime under the SkipTypeValidation flag as crossgen2 can now do it reliably

Related to the work in #120407

…erly
- Reduce the set of constraints that need to be loaded for Bounds and cast checking
TODO:
There is a path in InitTypeContext which I have #ifdef'd out as I don't understand the comment
The accessibility checking needs full loading now, as we don't have a scheme to just look at all the typedefs in a signature, and instead need to do a load of the full type and work from there. This could be revisited.
This is DRAFT as we now have an unused state WhichConstraintsToLoad::TypeOrMethodVarsOnly which we never use. (It could be used for the Bounds algorithm, but that isn't actually used without doing the more expensive logic which does access validation)
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

Should address issues in #120406

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.

- Currently it only handles interfaces defined on valuetypes
- Change it to work for interfaces that are required implementation of other interfaces
- (In that case, if the interface is generic, the special instantiation type is the first type parameter of the interface, not anything else.)
This change removes some safety checks that I can't find the rationale for. This may cause some entertaining failures in CI
- Tweak the logic so that it will attempt to avoid loading types if they are cannot have implementations of the method we're looking for
- This test was no longer actually forcing the type which is supposed to throw a TypeLoadException to load within the test
- Tweak the test to actually force the offending type to be loaded
@davidwrightondavidwrighton changed the title [DRAFT] Reduce constraint loadReduce types loaded on startup significantlyOct 8, 2025
@davidwrighton
davidwrighton marked this pull request as ready for review October 8, 2025 23:52

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 reduces type loading during startup by optimizing generic constraint handling and interface map operations. It achieves approximately 20% reduction in startup time for AWS lambda scenarios by deferring unnecessary type loads and using more efficient type checking algorithms.

Key changes:

  • Introduces selective constraint loading to avoid loading generic interface constraints when not needed
  • Optimizes interface map special marker types to work with interfaces, not just value types
  • Implements lazy evaluation strategies for default interface method resolution and static virtual method resolution

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharpNegative.ilAdds GetInterfaces() call to force interface type loading in test
src/coreclr/vm/typehandle.cppUpdates constraint loading calls to use selective loading approach
src/coreclr/vm/typedesc.hDefines WhichConstraintsToLoad enum and updates TypeVarTypeDesc constraint API
src/coreclr/vm/typedesc.cppImplements selective constraint loading with interface-aware logic
src/coreclr/vm/typectxt.cppUpdates type context initialization to handle constraint loading changes
src/coreclr/vm/siginfo.cppEnhances special marker type handling for generic interface instantiation
src/coreclr/vm/runtimehandles.cppUpdates constraint retrieval for reflection API
src/coreclr/vm/methodtablebuilder.cppExtends special marker optimization to interfaces and adds early exit optimizations
src/coreclr/vm/methodtable.inlUpdates interface implementation checking for new special instantiation logic
src/coreclr/vm/methodtable.hAdds GetSpecialInstantiationType method and interface equivalence checking
src/coreclr/vm/methodtable.cppImplements lazy interface loading, accessibility checking, and optimized method resolution
src/coreclr/vm/genmeth.cppUpdates constraint loading calls and removes unnecessary constraint loads
src/coreclr/vm/comdelegate.cppUpdates delegate constraint checking to use selective loading

Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test failure looks related

Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crossgen2 test still failing

Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/methodtable.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/methodtablebuilder.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotas

Copy link
Copy Markdown
Member

@EgorBot scenario-awslambda -arm -intel

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the tests are passing

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-interpreter

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton
davidwrighton merged commit 56484c9 into dotnet:mainOct 14, 2025
159 of 169 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0: https://github.com/dotnet/runtime/actions/runs/18504146328

@mangod9

Copy link
Copy Markdown
Member

/backport to release/10.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Nov 21, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0-staging (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@mangod9 an error occurred while backporting to release/10.0-staging. See the workflow output for details.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Nov 21, 2025
@jkotas

Copy link
Copy Markdown
Member

@mangod9 There is backport PR created already: #120712

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@jkotas@mangod9
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Reduce types loaded on startup significantly - #120459

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load
Oct 14, 2025
Merged

Reduce types loaded on startup significantly#120459
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Oct 7, 2025

Copy link
Copy Markdown
Member

Reduce the number of type loads triggered by complex generic constraints. Experiments show about a 20% reduction in startup time on a proxy of the AWS lambda scenario.

The fixes are:

  1. When a method/type has constraints, do not load the constraint types directly if they are generic interfaces. Instead, do accessibility checking and the constraint validation on the signature of the constraint instead.
  2. When a type is loaded, enhance the special marker type optimization in the interface map to allow Interfaces which require implementation of other interfaces to use the special marker type. Notably, use the special marker type so that if a generic interface's first type parameter is used as all of the generic type parameters of a required interface we use the special marker type to indicate that the type is loaded.
    • This also forces us to have a somewhat more complicated implementation of casting, since the previous model of special marker types could not experience an equivalent interface match
  3. When resolving a default interface method, attempt to avoid loading all the interface types associated with a type. Do so by changing the iteration of interfaces to check to see if the approximate interface could possibly have an implementation
  4. When resolving a static virtual method, attempt to avoid loading all the types of the MethodImpl records. Do so by doing a Method name check before loading the type.

In addition, fix a test so that it still throws when loading an invalid type. This required adding a path which forced the interface type to be loaded.

As part of testing this work, the lack of generic variable type safety checks was noticed in crossgen2, and the following changes were made

  • Add support for doing circularity checks on type and method generic parameters to the TypeValidationChecker in crossgen2
  • Add support for doing variance safety checks to the type loader in crossgen2

And in the runtime

  • Remove the circularity of type variables checks happening in generic method load, as it is redundant
  • Put all of the variance safety checks in the runtime under the SkipTypeValidation flag as crossgen2 can now do it reliably

Related to the work in #120407

…erly
- Reduce the set of constraints that need to be loaded for Bounds and cast checking
TODO:
There is a path in InitTypeContext which I have #ifdef'd out as I don't understand the comment
The accessibility checking needs full loading now, as we don't have a scheme to just look at all the typedefs in a signature, and instead need to do a load of the full type and work from there. This could be revisited.
This is DRAFT as we now have an unused state WhichConstraintsToLoad::TypeOrMethodVarsOnly which we never use. (It could be used for the Bounds algorithm, but that isn't actually used without doing the more expensive logic which does access validation)
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

Should address issues in #120406

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.

- Currently it only handles interfaces defined on valuetypes
- Change it to work for interfaces that are required implementation of other interfaces
- (In that case, if the interface is generic, the special instantiation type is the first type parameter of the interface, not anything else.)
This change removes some safety checks that I can't find the rationale for. This may cause some entertaining failures in CI
- Tweak the logic so that it will attempt to avoid loading types if they are cannot have implementations of the method we're looking for
- This test was no longer actually forcing the type which is supposed to throw a TypeLoadException to load within the test
- Tweak the test to actually force the offending type to be loaded
@davidwrightondavidwrighton changed the title [DRAFT] Reduce constraint loadReduce types loaded on startup significantlyOct 8, 2025
@davidwrighton
davidwrighton marked this pull request as ready for review October 8, 2025 23:52

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 reduces type loading during startup by optimizing generic constraint handling and interface map operations. It achieves approximately 20% reduction in startup time for AWS lambda scenarios by deferring unnecessary type loads and using more efficient type checking algorithms.

Key changes:

  • Introduces selective constraint loading to avoid loading generic interface constraints when not needed
  • Optimizes interface map special marker types to work with interfaces, not just value types
  • Implements lazy evaluation strategies for default interface method resolution and static virtual method resolution

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharpNegative.ilAdds GetInterfaces() call to force interface type loading in test
src/coreclr/vm/typehandle.cppUpdates constraint loading calls to use selective loading approach
src/coreclr/vm/typedesc.hDefines WhichConstraintsToLoad enum and updates TypeVarTypeDesc constraint API
src/coreclr/vm/typedesc.cppImplements selective constraint loading with interface-aware logic
src/coreclr/vm/typectxt.cppUpdates type context initialization to handle constraint loading changes
src/coreclr/vm/siginfo.cppEnhances special marker type handling for generic interface instantiation
src/coreclr/vm/runtimehandles.cppUpdates constraint retrieval for reflection API
src/coreclr/vm/methodtablebuilder.cppExtends special marker optimization to interfaces and adds early exit optimizations
src/coreclr/vm/methodtable.inlUpdates interface implementation checking for new special instantiation logic
src/coreclr/vm/methodtable.hAdds GetSpecialInstantiationType method and interface equivalence checking
src/coreclr/vm/methodtable.cppImplements lazy interface loading, accessibility checking, and optimized method resolution
src/coreclr/vm/genmeth.cppUpdates constraint loading calls and removes unnecessary constraint loads
src/coreclr/vm/comdelegate.cppUpdates delegate constraint checking to use selective loading

Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test failure looks related

Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crossgen2 test still failing

Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/methodtable.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/methodtablebuilder.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotas

Copy link
Copy Markdown
Member

@EgorBot scenario-awslambda -arm -intel

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the tests are passing

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-interpreter

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton
davidwrighton merged commit 56484c9 into dotnet:mainOct 14, 2025
159 of 169 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0: https://github.com/dotnet/runtime/actions/runs/18504146328

@mangod9

Copy link
Copy Markdown
Member

/backport to release/10.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Nov 21, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0-staging (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@mangod9 an error occurred while backporting to release/10.0-staging. See the workflow output for details.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Nov 21, 2025
@jkotas

Copy link
Copy Markdown
Member

@mangod9 There is backport PR created already: #120712

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@jkotas@mangod9
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Reduce types loaded on startup significantly - #120459

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load
Oct 14, 2025
Merged

Reduce types loaded on startup significantly#120459
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Oct 7, 2025

Copy link
Copy Markdown
Member

Reduce the number of type loads triggered by complex generic constraints. Experiments show about a 20% reduction in startup time on a proxy of the AWS lambda scenario.

The fixes are:

  1. When a method/type has constraints, do not load the constraint types directly if they are generic interfaces. Instead, do accessibility checking and the constraint validation on the signature of the constraint instead.
  2. When a type is loaded, enhance the special marker type optimization in the interface map to allow Interfaces which require implementation of other interfaces to use the special marker type. Notably, use the special marker type so that if a generic interface's first type parameter is used as all of the generic type parameters of a required interface we use the special marker type to indicate that the type is loaded.
    • This also forces us to have a somewhat more complicated implementation of casting, since the previous model of special marker types could not experience an equivalent interface match
  3. When resolving a default interface method, attempt to avoid loading all the interface types associated with a type. Do so by changing the iteration of interfaces to check to see if the approximate interface could possibly have an implementation
  4. When resolving a static virtual method, attempt to avoid loading all the types of the MethodImpl records. Do so by doing a Method name check before loading the type.

In addition, fix a test so that it still throws when loading an invalid type. This required adding a path which forced the interface type to be loaded.

As part of testing this work, the lack of generic variable type safety checks was noticed in crossgen2, and the following changes were made

  • Add support for doing circularity checks on type and method generic parameters to the TypeValidationChecker in crossgen2
  • Add support for doing variance safety checks to the type loader in crossgen2

And in the runtime

  • Remove the circularity of type variables checks happening in generic method load, as it is redundant
  • Put all of the variance safety checks in the runtime under the SkipTypeValidation flag as crossgen2 can now do it reliably

Related to the work in #120407

…erly
- Reduce the set of constraints that need to be loaded for Bounds and cast checking
TODO:
There is a path in InitTypeContext which I have #ifdef'd out as I don't understand the comment
The accessibility checking needs full loading now, as we don't have a scheme to just look at all the typedefs in a signature, and instead need to do a load of the full type and work from there. This could be revisited.
This is DRAFT as we now have an unused state WhichConstraintsToLoad::TypeOrMethodVarsOnly which we never use. (It could be used for the Bounds algorithm, but that isn't actually used without doing the more expensive logic which does access validation)
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

Should address issues in #120406

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.

- Currently it only handles interfaces defined on valuetypes
- Change it to work for interfaces that are required implementation of other interfaces
- (In that case, if the interface is generic, the special instantiation type is the first type parameter of the interface, not anything else.)
This change removes some safety checks that I can't find the rationale for. This may cause some entertaining failures in CI
- Tweak the logic so that it will attempt to avoid loading types if they are cannot have implementations of the method we're looking for
- This test was no longer actually forcing the type which is supposed to throw a TypeLoadException to load within the test
- Tweak the test to actually force the offending type to be loaded
@davidwrightondavidwrighton changed the title [DRAFT] Reduce constraint loadReduce types loaded on startup significantlyOct 8, 2025
@davidwrighton
davidwrighton marked this pull request as ready for review October 8, 2025 23:52

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 reduces type loading during startup by optimizing generic constraint handling and interface map operations. It achieves approximately 20% reduction in startup time for AWS lambda scenarios by deferring unnecessary type loads and using more efficient type checking algorithms.

Key changes:

  • Introduces selective constraint loading to avoid loading generic interface constraints when not needed
  • Optimizes interface map special marker types to work with interfaces, not just value types
  • Implements lazy evaluation strategies for default interface method resolution and static virtual method resolution

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharpNegative.ilAdds GetInterfaces() call to force interface type loading in test
src/coreclr/vm/typehandle.cppUpdates constraint loading calls to use selective loading approach
src/coreclr/vm/typedesc.hDefines WhichConstraintsToLoad enum and updates TypeVarTypeDesc constraint API
src/coreclr/vm/typedesc.cppImplements selective constraint loading with interface-aware logic
src/coreclr/vm/typectxt.cppUpdates type context initialization to handle constraint loading changes
src/coreclr/vm/siginfo.cppEnhances special marker type handling for generic interface instantiation
src/coreclr/vm/runtimehandles.cppUpdates constraint retrieval for reflection API
src/coreclr/vm/methodtablebuilder.cppExtends special marker optimization to interfaces and adds early exit optimizations
src/coreclr/vm/methodtable.inlUpdates interface implementation checking for new special instantiation logic
src/coreclr/vm/methodtable.hAdds GetSpecialInstantiationType method and interface equivalence checking
src/coreclr/vm/methodtable.cppImplements lazy interface loading, accessibility checking, and optimized method resolution
src/coreclr/vm/genmeth.cppUpdates constraint loading calls and removes unnecessary constraint loads
src/coreclr/vm/comdelegate.cppUpdates delegate constraint checking to use selective loading

Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test failure looks related

Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crossgen2 test still failing

Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/methodtable.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/methodtablebuilder.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotas

Copy link
Copy Markdown
Member

@EgorBot scenario-awslambda -arm -intel

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the tests are passing

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-interpreter

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton
davidwrighton merged commit 56484c9 into dotnet:mainOct 14, 2025
159 of 169 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0: https://github.com/dotnet/runtime/actions/runs/18504146328

@mangod9

Copy link
Copy Markdown
Member

/backport to release/10.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Nov 21, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0-staging (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@mangod9 an error occurred while backporting to release/10.0-staging. See the workflow output for details.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Nov 21, 2025
@jkotas

Copy link
Copy Markdown
Member

@mangod9 There is backport PR created already: #120712

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@jkotas@mangod9
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Reduce types loaded on startup significantly - #120459

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load
Oct 14, 2025
Merged

Reduce types loaded on startup significantly#120459
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Oct 7, 2025

Copy link
Copy Markdown
Member

Reduce the number of type loads triggered by complex generic constraints. Experiments show about a 20% reduction in startup time on a proxy of the AWS lambda scenario.

The fixes are:

  1. When a method/type has constraints, do not load the constraint types directly if they are generic interfaces. Instead, do accessibility checking and the constraint validation on the signature of the constraint instead.
  2. When a type is loaded, enhance the special marker type optimization in the interface map to allow Interfaces which require implementation of other interfaces to use the special marker type. Notably, use the special marker type so that if a generic interface's first type parameter is used as all of the generic type parameters of a required interface we use the special marker type to indicate that the type is loaded.
    • This also forces us to have a somewhat more complicated implementation of casting, since the previous model of special marker types could not experience an equivalent interface match
  3. When resolving a default interface method, attempt to avoid loading all the interface types associated with a type. Do so by changing the iteration of interfaces to check to see if the approximate interface could possibly have an implementation
  4. When resolving a static virtual method, attempt to avoid loading all the types of the MethodImpl records. Do so by doing a Method name check before loading the type.

In addition, fix a test so that it still throws when loading an invalid type. This required adding a path which forced the interface type to be loaded.

As part of testing this work, the lack of generic variable type safety checks was noticed in crossgen2, and the following changes were made

  • Add support for doing circularity checks on type and method generic parameters to the TypeValidationChecker in crossgen2
  • Add support for doing variance safety checks to the type loader in crossgen2

And in the runtime

  • Remove the circularity of type variables checks happening in generic method load, as it is redundant
  • Put all of the variance safety checks in the runtime under the SkipTypeValidation flag as crossgen2 can now do it reliably

Related to the work in #120407

…erly
- Reduce the set of constraints that need to be loaded for Bounds and cast checking
TODO:
There is a path in InitTypeContext which I have #ifdef'd out as I don't understand the comment
The accessibility checking needs full loading now, as we don't have a scheme to just look at all the typedefs in a signature, and instead need to do a load of the full type and work from there. This could be revisited.
This is DRAFT as we now have an unused state WhichConstraintsToLoad::TypeOrMethodVarsOnly which we never use. (It could be used for the Bounds algorithm, but that isn't actually used without doing the more expensive logic which does access validation)
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

Should address issues in #120406

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.

- Currently it only handles interfaces defined on valuetypes
- Change it to work for interfaces that are required implementation of other interfaces
- (In that case, if the interface is generic, the special instantiation type is the first type parameter of the interface, not anything else.)
This change removes some safety checks that I can't find the rationale for. This may cause some entertaining failures in CI
- Tweak the logic so that it will attempt to avoid loading types if they are cannot have implementations of the method we're looking for
- This test was no longer actually forcing the type which is supposed to throw a TypeLoadException to load within the test
- Tweak the test to actually force the offending type to be loaded
@davidwrightondavidwrighton changed the title [DRAFT] Reduce constraint loadReduce types loaded on startup significantlyOct 8, 2025
@davidwrighton
davidwrighton marked this pull request as ready for review October 8, 2025 23:52

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 reduces type loading during startup by optimizing generic constraint handling and interface map operations. It achieves approximately 20% reduction in startup time for AWS lambda scenarios by deferring unnecessary type loads and using more efficient type checking algorithms.

Key changes:

  • Introduces selective constraint loading to avoid loading generic interface constraints when not needed
  • Optimizes interface map special marker types to work with interfaces, not just value types
  • Implements lazy evaluation strategies for default interface method resolution and static virtual method resolution

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharpNegative.ilAdds GetInterfaces() call to force interface type loading in test
src/coreclr/vm/typehandle.cppUpdates constraint loading calls to use selective loading approach
src/coreclr/vm/typedesc.hDefines WhichConstraintsToLoad enum and updates TypeVarTypeDesc constraint API
src/coreclr/vm/typedesc.cppImplements selective constraint loading with interface-aware logic
src/coreclr/vm/typectxt.cppUpdates type context initialization to handle constraint loading changes
src/coreclr/vm/siginfo.cppEnhances special marker type handling for generic interface instantiation
src/coreclr/vm/runtimehandles.cppUpdates constraint retrieval for reflection API
src/coreclr/vm/methodtablebuilder.cppExtends special marker optimization to interfaces and adds early exit optimizations
src/coreclr/vm/methodtable.inlUpdates interface implementation checking for new special instantiation logic
src/coreclr/vm/methodtable.hAdds GetSpecialInstantiationType method and interface equivalence checking
src/coreclr/vm/methodtable.cppImplements lazy interface loading, accessibility checking, and optimized method resolution
src/coreclr/vm/genmeth.cppUpdates constraint loading calls and removes unnecessary constraint loads
src/coreclr/vm/comdelegate.cppUpdates delegate constraint checking to use selective loading

Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test failure looks related

Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crossgen2 test still failing

Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/methodtable.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/methodtablebuilder.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotas

Copy link
Copy Markdown
Member

@EgorBot scenario-awslambda -arm -intel

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the tests are passing

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-interpreter

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton
davidwrighton merged commit 56484c9 into dotnet:mainOct 14, 2025
159 of 169 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0: https://github.com/dotnet/runtime/actions/runs/18504146328

@mangod9

Copy link
Copy Markdown
Member

/backport to release/10.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Nov 21, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0-staging (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@mangod9 an error occurred while backporting to release/10.0-staging. See the workflow output for details.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Nov 21, 2025
@jkotas

Copy link
Copy Markdown
Member

@mangod9 There is backport PR created already: #120712

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@jkotas@mangod9
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Reduce types loaded on startup significantly - #120459

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load
Oct 14, 2025
Merged

Reduce types loaded on startup significantly#120459
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Oct 7, 2025

Copy link
Copy Markdown
Member

Reduce the number of type loads triggered by complex generic constraints. Experiments show about a 20% reduction in startup time on a proxy of the AWS lambda scenario.

The fixes are:

  1. When a method/type has constraints, do not load the constraint types directly if they are generic interfaces. Instead, do accessibility checking and the constraint validation on the signature of the constraint instead.
  2. When a type is loaded, enhance the special marker type optimization in the interface map to allow Interfaces which require implementation of other interfaces to use the special marker type. Notably, use the special marker type so that if a generic interface's first type parameter is used as all of the generic type parameters of a required interface we use the special marker type to indicate that the type is loaded.
    • This also forces us to have a somewhat more complicated implementation of casting, since the previous model of special marker types could not experience an equivalent interface match
  3. When resolving a default interface method, attempt to avoid loading all the interface types associated with a type. Do so by changing the iteration of interfaces to check to see if the approximate interface could possibly have an implementation
  4. When resolving a static virtual method, attempt to avoid loading all the types of the MethodImpl records. Do so by doing a Method name check before loading the type.

In addition, fix a test so that it still throws when loading an invalid type. This required adding a path which forced the interface type to be loaded.

As part of testing this work, the lack of generic variable type safety checks was noticed in crossgen2, and the following changes were made

  • Add support for doing circularity checks on type and method generic parameters to the TypeValidationChecker in crossgen2
  • Add support for doing variance safety checks to the type loader in crossgen2

And in the runtime

  • Remove the circularity of type variables checks happening in generic method load, as it is redundant
  • Put all of the variance safety checks in the runtime under the SkipTypeValidation flag as crossgen2 can now do it reliably

Related to the work in #120407

…erly
- Reduce the set of constraints that need to be loaded for Bounds and cast checking
TODO:
There is a path in InitTypeContext which I have #ifdef'd out as I don't understand the comment
The accessibility checking needs full loading now, as we don't have a scheme to just look at all the typedefs in a signature, and instead need to do a load of the full type and work from there. This could be revisited.
This is DRAFT as we now have an unused state WhichConstraintsToLoad::TypeOrMethodVarsOnly which we never use. (It could be used for the Bounds algorithm, but that isn't actually used without doing the more expensive logic which does access validation)
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

Should address issues in #120406

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.

- Currently it only handles interfaces defined on valuetypes
- Change it to work for interfaces that are required implementation of other interfaces
- (In that case, if the interface is generic, the special instantiation type is the first type parameter of the interface, not anything else.)
This change removes some safety checks that I can't find the rationale for. This may cause some entertaining failures in CI
- Tweak the logic so that it will attempt to avoid loading types if they are cannot have implementations of the method we're looking for
- This test was no longer actually forcing the type which is supposed to throw a TypeLoadException to load within the test
- Tweak the test to actually force the offending type to be loaded
@davidwrightondavidwrighton changed the title [DRAFT] Reduce constraint loadReduce types loaded on startup significantlyOct 8, 2025
@davidwrighton
davidwrighton marked this pull request as ready for review October 8, 2025 23:52

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 reduces type loading during startup by optimizing generic constraint handling and interface map operations. It achieves approximately 20% reduction in startup time for AWS lambda scenarios by deferring unnecessary type loads and using more efficient type checking algorithms.

Key changes:

  • Introduces selective constraint loading to avoid loading generic interface constraints when not needed
  • Optimizes interface map special marker types to work with interfaces, not just value types
  • Implements lazy evaluation strategies for default interface method resolution and static virtual method resolution

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharpNegative.ilAdds GetInterfaces() call to force interface type loading in test
src/coreclr/vm/typehandle.cppUpdates constraint loading calls to use selective loading approach
src/coreclr/vm/typedesc.hDefines WhichConstraintsToLoad enum and updates TypeVarTypeDesc constraint API
src/coreclr/vm/typedesc.cppImplements selective constraint loading with interface-aware logic
src/coreclr/vm/typectxt.cppUpdates type context initialization to handle constraint loading changes
src/coreclr/vm/siginfo.cppEnhances special marker type handling for generic interface instantiation
src/coreclr/vm/runtimehandles.cppUpdates constraint retrieval for reflection API
src/coreclr/vm/methodtablebuilder.cppExtends special marker optimization to interfaces and adds early exit optimizations
src/coreclr/vm/methodtable.inlUpdates interface implementation checking for new special instantiation logic
src/coreclr/vm/methodtable.hAdds GetSpecialInstantiationType method and interface equivalence checking
src/coreclr/vm/methodtable.cppImplements lazy interface loading, accessibility checking, and optimized method resolution
src/coreclr/vm/genmeth.cppUpdates constraint loading calls and removes unnecessary constraint loads
src/coreclr/vm/comdelegate.cppUpdates delegate constraint checking to use selective loading

Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test failure looks related

Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crossgen2 test still failing

Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/methodtable.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/methodtablebuilder.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotas

Copy link
Copy Markdown
Member

@EgorBot scenario-awslambda -arm -intel

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the tests are passing

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-interpreter

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton
davidwrighton merged commit 56484c9 into dotnet:mainOct 14, 2025
159 of 169 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0: https://github.com/dotnet/runtime/actions/runs/18504146328

@mangod9

Copy link
Copy Markdown
Member

/backport to release/10.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Nov 21, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0-staging (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@mangod9 an error occurred while backporting to release/10.0-staging. See the workflow output for details.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Nov 21, 2025
@jkotas

Copy link
Copy Markdown
Member

@mangod9 There is backport PR created already: #120712

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@jkotas@mangod9
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Reduce types loaded on startup significantly - #120459

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load
Oct 14, 2025
Merged

Reduce types loaded on startup significantly#120459
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Oct 7, 2025

Copy link
Copy Markdown
Member

Reduce the number of type loads triggered by complex generic constraints. Experiments show about a 20% reduction in startup time on a proxy of the AWS lambda scenario.

The fixes are:

  1. When a method/type has constraints, do not load the constraint types directly if they are generic interfaces. Instead, do accessibility checking and the constraint validation on the signature of the constraint instead.
  2. When a type is loaded, enhance the special marker type optimization in the interface map to allow Interfaces which require implementation of other interfaces to use the special marker type. Notably, use the special marker type so that if a generic interface's first type parameter is used as all of the generic type parameters of a required interface we use the special marker type to indicate that the type is loaded.
    • This also forces us to have a somewhat more complicated implementation of casting, since the previous model of special marker types could not experience an equivalent interface match
  3. When resolving a default interface method, attempt to avoid loading all the interface types associated with a type. Do so by changing the iteration of interfaces to check to see if the approximate interface could possibly have an implementation
  4. When resolving a static virtual method, attempt to avoid loading all the types of the MethodImpl records. Do so by doing a Method name check before loading the type.

In addition, fix a test so that it still throws when loading an invalid type. This required adding a path which forced the interface type to be loaded.

As part of testing this work, the lack of generic variable type safety checks was noticed in crossgen2, and the following changes were made

  • Add support for doing circularity checks on type and method generic parameters to the TypeValidationChecker in crossgen2
  • Add support for doing variance safety checks to the type loader in crossgen2

And in the runtime

  • Remove the circularity of type variables checks happening in generic method load, as it is redundant
  • Put all of the variance safety checks in the runtime under the SkipTypeValidation flag as crossgen2 can now do it reliably

Related to the work in #120407

…erly
- Reduce the set of constraints that need to be loaded for Bounds and cast checking
TODO:
There is a path in InitTypeContext which I have #ifdef'd out as I don't understand the comment
The accessibility checking needs full loading now, as we don't have a scheme to just look at all the typedefs in a signature, and instead need to do a load of the full type and work from there. This could be revisited.
This is DRAFT as we now have an unused state WhichConstraintsToLoad::TypeOrMethodVarsOnly which we never use. (It could be used for the Bounds algorithm, but that isn't actually used without doing the more expensive logic which does access validation)
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

Should address issues in #120406

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.

- Currently it only handles interfaces defined on valuetypes
- Change it to work for interfaces that are required implementation of other interfaces
- (In that case, if the interface is generic, the special instantiation type is the first type parameter of the interface, not anything else.)
This change removes some safety checks that I can't find the rationale for. This may cause some entertaining failures in CI
- Tweak the logic so that it will attempt to avoid loading types if they are cannot have implementations of the method we're looking for
- This test was no longer actually forcing the type which is supposed to throw a TypeLoadException to load within the test
- Tweak the test to actually force the offending type to be loaded
@davidwrightondavidwrighton changed the title [DRAFT] Reduce constraint loadReduce types loaded on startup significantlyOct 8, 2025
@davidwrighton
davidwrighton marked this pull request as ready for review October 8, 2025 23:52

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 reduces type loading during startup by optimizing generic constraint handling and interface map operations. It achieves approximately 20% reduction in startup time for AWS lambda scenarios by deferring unnecessary type loads and using more efficient type checking algorithms.

Key changes:

  • Introduces selective constraint loading to avoid loading generic interface constraints when not needed
  • Optimizes interface map special marker types to work with interfaces, not just value types
  • Implements lazy evaluation strategies for default interface method resolution and static virtual method resolution

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharpNegative.ilAdds GetInterfaces() call to force interface type loading in test
src/coreclr/vm/typehandle.cppUpdates constraint loading calls to use selective loading approach
src/coreclr/vm/typedesc.hDefines WhichConstraintsToLoad enum and updates TypeVarTypeDesc constraint API
src/coreclr/vm/typedesc.cppImplements selective constraint loading with interface-aware logic
src/coreclr/vm/typectxt.cppUpdates type context initialization to handle constraint loading changes
src/coreclr/vm/siginfo.cppEnhances special marker type handling for generic interface instantiation
src/coreclr/vm/runtimehandles.cppUpdates constraint retrieval for reflection API
src/coreclr/vm/methodtablebuilder.cppExtends special marker optimization to interfaces and adds early exit optimizations
src/coreclr/vm/methodtable.inlUpdates interface implementation checking for new special instantiation logic
src/coreclr/vm/methodtable.hAdds GetSpecialInstantiationType method and interface equivalence checking
src/coreclr/vm/methodtable.cppImplements lazy interface loading, accessibility checking, and optimized method resolution
src/coreclr/vm/genmeth.cppUpdates constraint loading calls and removes unnecessary constraint loads
src/coreclr/vm/comdelegate.cppUpdates delegate constraint checking to use selective loading

Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test failure looks related

Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crossgen2 test still failing

Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/methodtable.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/methodtablebuilder.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotas

Copy link
Copy Markdown
Member

@EgorBot scenario-awslambda -arm -intel

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the tests are passing

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-interpreter

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton
davidwrighton merged commit 56484c9 into dotnet:mainOct 14, 2025
159 of 169 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0: https://github.com/dotnet/runtime/actions/runs/18504146328

@mangod9

Copy link
Copy Markdown
Member

/backport to release/10.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Nov 21, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0-staging (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@mangod9 an error occurred while backporting to release/10.0-staging. See the workflow output for details.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Nov 21, 2025
@jkotas

Copy link
Copy Markdown
Member

@mangod9 There is backport PR created already: #120712

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@jkotas@mangod9
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Reduce types loaded on startup significantly - #120459

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load
Oct 14, 2025
Merged

Reduce types loaded on startup significantly#120459
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Oct 7, 2025

Copy link
Copy Markdown
Member

Reduce the number of type loads triggered by complex generic constraints. Experiments show about a 20% reduction in startup time on a proxy of the AWS lambda scenario.

The fixes are:

  1. When a method/type has constraints, do not load the constraint types directly if they are generic interfaces. Instead, do accessibility checking and the constraint validation on the signature of the constraint instead.
  2. When a type is loaded, enhance the special marker type optimization in the interface map to allow Interfaces which require implementation of other interfaces to use the special marker type. Notably, use the special marker type so that if a generic interface's first type parameter is used as all of the generic type parameters of a required interface we use the special marker type to indicate that the type is loaded.
    • This also forces us to have a somewhat more complicated implementation of casting, since the previous model of special marker types could not experience an equivalent interface match
  3. When resolving a default interface method, attempt to avoid loading all the interface types associated with a type. Do so by changing the iteration of interfaces to check to see if the approximate interface could possibly have an implementation
  4. When resolving a static virtual method, attempt to avoid loading all the types of the MethodImpl records. Do so by doing a Method name check before loading the type.

In addition, fix a test so that it still throws when loading an invalid type. This required adding a path which forced the interface type to be loaded.

As part of testing this work, the lack of generic variable type safety checks was noticed in crossgen2, and the following changes were made

  • Add support for doing circularity checks on type and method generic parameters to the TypeValidationChecker in crossgen2
  • Add support for doing variance safety checks to the type loader in crossgen2

And in the runtime

  • Remove the circularity of type variables checks happening in generic method load, as it is redundant
  • Put all of the variance safety checks in the runtime under the SkipTypeValidation flag as crossgen2 can now do it reliably

Related to the work in #120407

…erly
- Reduce the set of constraints that need to be loaded for Bounds and cast checking
TODO:
There is a path in InitTypeContext which I have #ifdef'd out as I don't understand the comment
The accessibility checking needs full loading now, as we don't have a scheme to just look at all the typedefs in a signature, and instead need to do a load of the full type and work from there. This could be revisited.
This is DRAFT as we now have an unused state WhichConstraintsToLoad::TypeOrMethodVarsOnly which we never use. (It could be used for the Bounds algorithm, but that isn't actually used without doing the more expensive logic which does access validation)
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

Should address issues in #120406

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.

- Currently it only handles interfaces defined on valuetypes
- Change it to work for interfaces that are required implementation of other interfaces
- (In that case, if the interface is generic, the special instantiation type is the first type parameter of the interface, not anything else.)
This change removes some safety checks that I can't find the rationale for. This may cause some entertaining failures in CI
- Tweak the logic so that it will attempt to avoid loading types if they are cannot have implementations of the method we're looking for
- This test was no longer actually forcing the type which is supposed to throw a TypeLoadException to load within the test
- Tweak the test to actually force the offending type to be loaded
@davidwrightondavidwrighton changed the title [DRAFT] Reduce constraint loadReduce types loaded on startup significantlyOct 8, 2025
@davidwrighton
davidwrighton marked this pull request as ready for review October 8, 2025 23:52

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 reduces type loading during startup by optimizing generic constraint handling and interface map operations. It achieves approximately 20% reduction in startup time for AWS lambda scenarios by deferring unnecessary type loads and using more efficient type checking algorithms.

Key changes:

  • Introduces selective constraint loading to avoid loading generic interface constraints when not needed
  • Optimizes interface map special marker types to work with interfaces, not just value types
  • Implements lazy evaluation strategies for default interface method resolution and static virtual method resolution

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharpNegative.ilAdds GetInterfaces() call to force interface type loading in test
src/coreclr/vm/typehandle.cppUpdates constraint loading calls to use selective loading approach
src/coreclr/vm/typedesc.hDefines WhichConstraintsToLoad enum and updates TypeVarTypeDesc constraint API
src/coreclr/vm/typedesc.cppImplements selective constraint loading with interface-aware logic
src/coreclr/vm/typectxt.cppUpdates type context initialization to handle constraint loading changes
src/coreclr/vm/siginfo.cppEnhances special marker type handling for generic interface instantiation
src/coreclr/vm/runtimehandles.cppUpdates constraint retrieval for reflection API
src/coreclr/vm/methodtablebuilder.cppExtends special marker optimization to interfaces and adds early exit optimizations
src/coreclr/vm/methodtable.inlUpdates interface implementation checking for new special instantiation logic
src/coreclr/vm/methodtable.hAdds GetSpecialInstantiationType method and interface equivalence checking
src/coreclr/vm/methodtable.cppImplements lazy interface loading, accessibility checking, and optimized method resolution
src/coreclr/vm/genmeth.cppUpdates constraint loading calls and removes unnecessary constraint loads
src/coreclr/vm/comdelegate.cppUpdates delegate constraint checking to use selective loading

Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test failure looks related

Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crossgen2 test still failing

Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/methodtable.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/methodtablebuilder.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotas

Copy link
Copy Markdown
Member

@EgorBot scenario-awslambda -arm -intel

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the tests are passing

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-interpreter

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton
davidwrighton merged commit 56484c9 into dotnet:mainOct 14, 2025
159 of 169 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0: https://github.com/dotnet/runtime/actions/runs/18504146328

@mangod9

Copy link
Copy Markdown
Member

/backport to release/10.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Nov 21, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0-staging (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@mangod9 an error occurred while backporting to release/10.0-staging. See the workflow output for details.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Nov 21, 2025
@jkotas

Copy link
Copy Markdown
Member

@mangod9 There is backport PR created already: #120712

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@jkotas@mangod9
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Reduce types loaded on startup significantly - #120459

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load
Oct 14, 2025
Merged

Reduce types loaded on startup significantly#120459
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:reduce_constraint_load

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Oct 7, 2025

Copy link
Copy Markdown
Member

Reduce the number of type loads triggered by complex generic constraints. Experiments show about a 20% reduction in startup time on a proxy of the AWS lambda scenario.

The fixes are:

  1. When a method/type has constraints, do not load the constraint types directly if they are generic interfaces. Instead, do accessibility checking and the constraint validation on the signature of the constraint instead.
  2. When a type is loaded, enhance the special marker type optimization in the interface map to allow Interfaces which require implementation of other interfaces to use the special marker type. Notably, use the special marker type so that if a generic interface's first type parameter is used as all of the generic type parameters of a required interface we use the special marker type to indicate that the type is loaded.
    • This also forces us to have a somewhat more complicated implementation of casting, since the previous model of special marker types could not experience an equivalent interface match
  3. When resolving a default interface method, attempt to avoid loading all the interface types associated with a type. Do so by changing the iteration of interfaces to check to see if the approximate interface could possibly have an implementation
  4. When resolving a static virtual method, attempt to avoid loading all the types of the MethodImpl records. Do so by doing a Method name check before loading the type.

In addition, fix a test so that it still throws when loading an invalid type. This required adding a path which forced the interface type to be loaded.

As part of testing this work, the lack of generic variable type safety checks was noticed in crossgen2, and the following changes were made

  • Add support for doing circularity checks on type and method generic parameters to the TypeValidationChecker in crossgen2
  • Add support for doing variance safety checks to the type loader in crossgen2

And in the runtime

  • Remove the circularity of type variables checks happening in generic method load, as it is redundant
  • Put all of the variance safety checks in the runtime under the SkipTypeValidation flag as crossgen2 can now do it reliably

Related to the work in #120407

…erly
- Reduce the set of constraints that need to be loaded for Bounds and cast checking
TODO:
There is a path in InitTypeContext which I have #ifdef'd out as I don't understand the comment
The accessibility checking needs full loading now, as we don't have a scheme to just look at all the typedefs in a signature, and instead need to do a load of the full type and work from there. This could be revisited.
This is DRAFT as we now have an unused state WhichConstraintsToLoad::TypeOrMethodVarsOnly which we never use. (It could be used for the Bounds algorithm, but that isn't actually used without doing the more expensive logic which does access validation)
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

Should address issues in #120406

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.

- Currently it only handles interfaces defined on valuetypes
- Change it to work for interfaces that are required implementation of other interfaces
- (In that case, if the interface is generic, the special instantiation type is the first type parameter of the interface, not anything else.)
This change removes some safety checks that I can't find the rationale for. This may cause some entertaining failures in CI
- Tweak the logic so that it will attempt to avoid loading types if they are cannot have implementations of the method we're looking for
- This test was no longer actually forcing the type which is supposed to throw a TypeLoadException to load within the test
- Tweak the test to actually force the offending type to be loaded
@davidwrightondavidwrighton changed the title [DRAFT] Reduce constraint loadReduce types loaded on startup significantlyOct 8, 2025
@davidwrighton
davidwrighton marked this pull request as ready for review October 8, 2025 23:52

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 reduces type loading during startup by optimizing generic constraint handling and interface map operations. It achieves approximately 20% reduction in startup time for AWS lambda scenarios by deferring unnecessary type loads and using more efficient type checking algorithms.

Key changes:

  • Introduces selective constraint loading to avoid loading generic interface constraints when not needed
  • Optimizes interface map special marker types to work with interfaces, not just value types
  • Implements lazy evaluation strategies for default interface method resolution and static virtual method resolution

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharpNegative.ilAdds GetInterfaces() call to force interface type loading in test
src/coreclr/vm/typehandle.cppUpdates constraint loading calls to use selective loading approach
src/coreclr/vm/typedesc.hDefines WhichConstraintsToLoad enum and updates TypeVarTypeDesc constraint API
src/coreclr/vm/typedesc.cppImplements selective constraint loading with interface-aware logic
src/coreclr/vm/typectxt.cppUpdates type context initialization to handle constraint loading changes
src/coreclr/vm/siginfo.cppEnhances special marker type handling for generic interface instantiation
src/coreclr/vm/runtimehandles.cppUpdates constraint retrieval for reflection API
src/coreclr/vm/methodtablebuilder.cppExtends special marker optimization to interfaces and adds early exit optimizations
src/coreclr/vm/methodtable.inlUpdates interface implementation checking for new special instantiation logic
src/coreclr/vm/methodtable.hAdds GetSpecialInstantiationType method and interface equivalence checking
src/coreclr/vm/methodtable.cppImplements lazy interface loading, accessibility checking, and optimized method resolution
src/coreclr/vm/genmeth.cppUpdates constraint loading calls and removes unnecessary constraint loads
src/coreclr/vm/comdelegate.cppUpdates delegate constraint checking to use selective loading

Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/typedesc.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test failure looks related

Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crossgen2 test still failing

Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/genmeth.cpp Outdated
Comment threadsrc/coreclr/vm/methodtable.cpp
Comment threadsrc/coreclr/vm/methodtable.cpp Outdated
Comment threadsrc/coreclr/vm/methodtablebuilder.cpp Outdated
@jkotas

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkotas

Copy link
Copy Markdown
Member

@EgorBot scenario-awslambda -arm -intel

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the tests are passing

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-interpreter

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton
davidwrighton merged commit 56484c9 into dotnet:mainOct 14, 2025
159 of 169 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0: https://github.com/dotnet/runtime/actions/runs/18504146328

@mangod9

Copy link
Copy Markdown
Member

/backport to release/10.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Nov 21, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0-staging (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@mangod9 an error occurred while backporting to release/10.0-staging. See the workflow output for details.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Nov 21, 2025
@jkotas

Copy link
Copy Markdown
Member

@mangod9 There is backport PR created already: #120712

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@jkotas@mangod9