This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Reflection performance tweaks & cleanup #21737
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Member
jkotas
commented
Jan 1, 2019
- Delete internal "Unsafe" field getters/setters. They performance was very close (within 10%) of the regular getters/setters.
- Made a few performance tweaks in reflection to make reflection faster overall. The regular field getters/setters are faster than what the unsafe ones used to be with this change.
Related to discussion in dotnet/corert#6747 (comment) |
@dotnet-bot test Ubuntu x64 Checked CoreFX Tests please |
stephentoub
approved these changes
Jan 2, 2019
|
||
return m_fieldType; | ||
Type Initialize() => m_fieldType = new Signature(this, m_declaringType).FieldType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't need to be NoInlining (in which case it also currently can't be local)?
|
||
Debug.Assert(cache != null); | ||
return cache; | ||
RuntimeTypeCache cache = Unsafe.As<RuntimeTypeCache>(GCHandle.InternalGet(m_cache)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the unsafe casting important for perf in this Initialize method?
- Delete internal "Unsafe" field getters/setters. They performance was very close (within 10%) of the regular getters/setters. - Made a few performance tweaks in reflection to make reflection faster overall. The regular field getters/setters are faster than what the unsafe ones used to be with this change.
7dab022
to
de1c866
Compare
janvorli
added a commit
to janvorli/coreclr
that referenced
this pull request
Mar 9, 2020
When there is a race calling RuntimeType.InitializeCache, each of the racing threads creates a new GC handle using new RuntimeTypeHandle(this).GetGCHandle(GCHandleType.WeakTrackResurrection); This ends up calling RuntimeTypeHandle::GetGCHandle native method that adds the allocated handle into the handle cleanup list of the AssemblyLoaderAllocator specific for the runtime type. All but the winning thread then call GCHandle.InternalFree on the just allocated handle. That frees the handle, but leaves it on the cleanup list of the loader allocator. The same handle can be later allocated for some other purpose. When the AssemblyLoaderAllocator is being destroyed, all the handles on the cleanup list are destroyed too. So it destroys also the handle that was left on the cleanup list incorrectly. That can cause all kinds of hard to diagnose issues, like the dotnet/runtime#32171. This change fixes it by adding a FreeGCHandle method on the RuntimeTypeHandle that besides freeing the handle also removes it from the cleanup list of the related AssemblyLoadContext. ## Customer impact Hard to diagnose crashes in the runtime caused by closing of random GC handles. The customer that has reported this issue was using collectible assemblies and it was resulting in collecting LoaderAllocator that was still in use and it lead to crashes at various places. ## Regression? Yes, it was introduced in 3.0. In 2.1 and 2.2, the thread that loses the race destroys the handle only if the type was not in a collectible assembly. Since the non-collectible assemblies LoaderAllocator is never destroyed, the handles were never cleaned up and so no problem could occur. It was introduced in dotnet#21737 ##Testing Customer affected by the issue heavily has tested a fixed version and reported the issue doesn't occur anymore. ## Risk Low, the new code is executed at single place once per process runtine only when a thread races for allocating the GC handle with another one and loses the race.
Anipik
pushed a commit
that referenced
this pull request
Mar 25, 2020
* Port to 3.1: Fix allocation of RuntimeTypeCache GC handle When there is a race calling RuntimeType.InitializeCache, each of the racing threads creates a new GC handle using new RuntimeTypeHandle(this).GetGCHandle(GCHandleType.WeakTrackResurrection); This ends up calling RuntimeTypeHandle::GetGCHandle native method that adds the allocated handle into the handle cleanup list of the AssemblyLoaderAllocator specific for the runtime type. All but the winning thread then call GCHandle.InternalFree on the just allocated handle. That frees the handle, but leaves it on the cleanup list of the loader allocator. The same handle can be later allocated for some other purpose. When the AssemblyLoaderAllocator is being destroyed, all the handles on the cleanup list are destroyed too. So it destroys also the handle that was left on the cleanup list incorrectly. That can cause all kinds of hard to diagnose issues, like the dotnet/runtime#32171. This change fixes it by adding a FreeGCHandle method on the RuntimeTypeHandle that besides freeing the handle also removes it from the cleanup list of the related AssemblyLoadContext. ## Customer impact Hard to diagnose crashes in the runtime caused by closing of random GC handles. The customer that has reported this issue was using collectible assemblies and it was resulting in collecting LoaderAllocator that was still in use and it lead to crashes at various places. ## Regression? Yes, it was introduced in 3.0. In 2.1 and 2.2, the thread that loses the race destroys the handle only if the type was not in a collectible assembly. Since the non-collectible assemblies LoaderAllocator is never destroyed, the handles were never cleaned up and so no problem could occur. It was introduced in #21737 ##Testing Customer affected by the issue heavily has tested a fixed version and reported the issue doesn't occur anymore. ## Risk Low, the new code is executed at single place once per process runtine only when a thread races for allocating the GC handle with another one and loses the race. * Fix build break - subtle differences from runtime master
picenka21
pushed a commit
to picenka21/runtime
that referenced
this pull request
Feb 18, 2022
- Delete internal "Unsafe" field getters/setters. They performance was very close (within 10%) of the regular getters/setters. - Made a few performance tweaks in reflection to make reflection faster overall. The regular field getters/setters are faster than what the unsafe ones used to be with this change. Commit migrated from dotnet/coreclr@a626939
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.