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
Optimization: Reduce many array allocations in GetCustomAtttributes()'s inherited path #20779
Merged
jkotas
merged 8 commits into
dotnet:master
from
NickCraver:craver/reduce-attribute-misses
Nov 4, 2018
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
622b74e
Optimization: avoid 2 array allocations in inherited attribute misses
NickCraver cb2305f
Move RuntimeType empty array cache generation to Attribute.CreateAttr…
NickCraver 1b459b9
CustomAttributes: remove needless array copy in the inherited hit case
NickCraver d6004ae
GetCusomAttributes: use ListBuilder<object> for inheritance crawls
NickCraver 496a760
Attribute caching: use Array.CreateInstance() directly on RuntimeType
NickCraver 70dc679
Ref passing for RuntimeType.ListBuilder<object> & CustomAttribute sim…
NickCraver f6307e3
Merge upstream master
NickCraver b2ac5c6
Tidy up RuntimeType casts from object
NickCraver File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,7 +75,7 @@ internal enum MemberListType | |
} | ||
|
||
// Helper to build lists of MemberInfos. Special cased to avoid allocations for lists of one element. | ||
private struct ListBuilder<T> where T : class | ||
internal struct ListBuilder<T> where T : class | ||
{ | ||
private T[] _items; | ||
private T _item; | ||
|
@@ -1453,6 +1453,7 @@ internal RuntimeType ReflectedType | |
private static object s_methodInstantiationsLock; | ||
private string m_defaultMemberName; | ||
private object m_genericCache; // Generic cache for rare scenario specific data. It is used to cache Enum names and values. | ||
private object[] _emptyArray; // Object array cache for Attribute.GetCustomAttributes() pathological no-result case. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this can reuse |
||
#endregion | ||
|
||
#region Constructor | ||
|
@@ -1620,6 +1621,11 @@ internal string GetDefaultMemberName() | |
|
||
return m_defaultMemberName; | ||
} | ||
|
||
internal object[] GetEmptyArray() | ||
{ | ||
return _emptyArray ?? (_emptyArray = (object[])Array.CreateInstance(m_runtimeType, 0)); | ||
} | ||
#endregion | ||
|
||
#region Caches Accessors | ||
|
@@ -3533,6 +3539,11 @@ public override Type GetElementType() | |
{ | ||
return RuntimeTypeHandle.GetElementType(this); | ||
} | ||
|
||
internal object[] GetEmptyArray() | ||
{ | ||
return Cache.GetEmptyArray(); | ||
} | ||
#endregion | ||
|
||
#region Enums | ||
|
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.
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.
You can replace
List<object>
withListBuilder<object>
to save another allocation.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.
Not sure I follow this note -
ListBuilder<T>
is private insideRuntimeType
and expects a known capacity at start, do you want to consider changing either of those things? Or aiming atValueListBuilder<T>
?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.
Default
ListBuilder<T>
constructor does not need capacity, and changing it to internal should be fine too.ValueListBuilder
would work too, but probably not as well asListBuilder<T>
in this case.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.
Got it - I'm still figuring out what scope of changes is acceptable in which areas of CoreFX/CoreCLR, so I really appreciate the feedback!
ListBuilder<T>
is exposed/used now, and I've greatly expanded the benchmarks above to illustrate the gains there. Thanks!