diff options
author | Jan Kotas <jkotas@microsoft.com> | 2019-01-03 23:05:49 -1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-03 23:05:49 -1000 |
commit | a6269391cf04c656e9d472e1101e1ec670ecd605 (patch) | |
tree | d54e0b5a520b88413adb0d95f338ee4d42bc55a6 /src/System.Private.CoreLib/src/System/RtType.cs | |
parent | 7d67f73b7223620b709b2c7e33e0f6e3cef5a7e8 (diff) | |
download | coreclr-a6269391cf04c656e9d472e1101e1ec670ecd605.tar.gz coreclr-a6269391cf04c656e9d472e1101e1ec670ecd605.tar.bz2 coreclr-a6269391cf04c656e9d472e1101e1ec670ecd605.zip |
Reflection performance tweaks & cleanup (#21737)
- 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.
Diffstat (limited to 'src/System.Private.CoreLib/src/System/RtType.cs')
-rw-r--r-- | src/System.Private.CoreLib/src/System/RtType.cs | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/src/System.Private.CoreLib/src/System/RtType.cs b/src/System.Private.CoreLib/src/System/RtType.cs index 0fcbd3b54c..dd30ea404c 100644 --- a/src/System.Private.CoreLib/src/System/RtType.cs +++ b/src/System.Private.CoreLib/src/System/RtType.cs @@ -14,6 +14,8 @@ using System.Threading; using DebuggerStepThroughAttribute = System.Diagnostics.DebuggerStepThroughAttribute; using MdToken = System.Reflection.MetadataToken; +using Internal.Runtime.CompilerServices; + namespace System { // this is a work around to get the concept of a calli. It's not as fast but it would be interesting to @@ -2379,30 +2381,44 @@ namespace System private RuntimeTypeCache Cache { + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - if (m_cache == IntPtr.Zero) + if (m_cache != IntPtr.Zero) { - IntPtr newgcHandle = new RuntimeTypeHandle(this).GetGCHandle(GCHandleType.WeakTrackResurrection); - IntPtr gcHandle = Interlocked.CompareExchange(ref m_cache, newgcHandle, IntPtr.Zero); - // Leak the handle if the type is collectible. It will be reclaimed when - // the type goes away. - if (gcHandle != IntPtr.Zero && !IsCollectible) - GCHandle.InternalFree(newgcHandle); + object cache = GCHandle.InternalGet(m_cache); + if (cache != null) + { + Debug.Assert(cache is RuntimeTypeCache); + return Unsafe.As<RuntimeTypeCache>(cache); + } } + return InitializeCache(); + } + } - RuntimeTypeCache cache = GCHandle.InternalGet(m_cache) as RuntimeTypeCache; - if (cache == null) - { - cache = new RuntimeTypeCache(this); - RuntimeTypeCache existingCache = GCHandle.InternalCompareExchange(m_cache, cache, null, false) as RuntimeTypeCache; - if (existingCache != null) - cache = existingCache; - } + [MethodImpl(MethodImplOptions.NoInlining)] + private RuntimeTypeCache InitializeCache() + { + if (m_cache == IntPtr.Zero) + { + IntPtr newgcHandle = new RuntimeTypeHandle(this).GetGCHandle(GCHandleType.WeakTrackResurrection); + IntPtr gcHandle = Interlocked.CompareExchange(ref m_cache, newgcHandle, IntPtr.Zero); + if (gcHandle != IntPtr.Zero) + GCHandle.InternalFree(newgcHandle); + } - Debug.Assert(cache != null); - return cache; + RuntimeTypeCache cache = (RuntimeTypeCache)GCHandle.InternalGet(m_cache); + if (cache == null) + { + cache = new RuntimeTypeCache(this); + RuntimeTypeCache existingCache = (RuntimeTypeCache)GCHandle.InternalCompareExchange(m_cache, cache, null, false); + if (existingCache != null) + cache = existingCache; } + + Debug.Assert(cache != null); + return cache; } private string GetDefaultMemberName() |