-
Notifications
You must be signed in to change notification settings - Fork 2.7k
DictionarySlim backport improvements: remove null check on insert #22599
Conversation
It is explainable that you are not able to measure any throughput gains from this change. The one extra null check you are removing will be very well predicted when TryInsert is called in the loop because of it is rarely taken. It means that it will costs next to nothing, especially given the size and complexity of the method that it is part of. On the other hand, this increases Dictionary static footprint (adds static constructor, adds a static field, adds extra or more checks to multiple other places). Thanks for giving it a try, but this change does not look like an improvement to me. |
I agree with all your analysis but I have to show that I did my homework |
|
||
// Default initialization to avoid null check for every insert | ||
// Reads will fail and first add cause a resize into a real array | ||
if (_entries is null) |
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.
Won't it always be null?
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.
If capacity passed is > 0 we call Initialize(capacity)
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.
Then wouldn't this be an else off of that? Or initialize these first and then do that check?
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.
Yep
@@ -53,6 +52,7 @@ private struct Entry | |||
private IEqualityComparer<TKey> _comparer; | |||
private KeyCollection _keys; | |||
private ValueCollection _values; | |||
private static readonly Entry[] InitialEntries = new Entry[1] { new Entry() { hashCode = -1 } }; |
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.
s_initialEntries
int currentCapacity = _entries == null ? 0 : _entries.Length; | ||
|
||
// _entries.Length == 1 is dummy entries | ||
int currentCapacity = _entries.Length == 1 ? 0 : _entries.Length; |
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.
So it's removing a null check but adding in one or more _entries.Length == 1 checks?
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.
The idea was remove check null for main method that adds so here we don't have null anymore but dummy len. BTW I agree with @jkotas and this improvement is not good for Dictionary, but as I said I published my thought/result
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.
#22599 (comment) do you agree?
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.
do you agree?
Yes. Thanks.
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.
I'm exploring if some improvement done on DictionartSlim(corefxlab) can improve Dictionary.
Thanks for the attempt. |
Done |
Thank's for your time! |
Thanks for trying. BTW this was not to improve throughput but reduce footprint of empty dictionaries. |
Ah ok from issue I misunderstood |
contributes to https://github.com/dotnet/corefx/issues/33392
@danmosemsft sorry for delay I had to learn new funny tools.
I thought to tackle backporting one point at time.
Due diligence:
Asm before:
After
I run some perf test and added one more to avoid ctor(not foundamental but one more test is better than nothing, thank's @benaadams for your help with tools and for test idea)
Perf before
After
Comparer result thank's to @adamsitnik
No Slower results for the provided threshold = 1% and noise filter = 0.3ns.
BTW it's not easy compare as expected, sometimes I get better result and other worste.
/cc @AnthonyLloyd @Zhentar