- Notifications
You must be signed in to change notification settings - Fork5.2k
Faster Dictionary clone#41944
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Faster Dictionary clone#41944
Uh oh!
There was an error while loading.Please reload this page.
Conversation
ghost commentedSep 7, 2020
Tagging subscribers to this area:@eiriktsarpalis,@jeffhandley |
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
mjsabby commentedSep 7, 2020
@danmosemsft it would be nice if we also made this improvement in DictionarySlim. For specific cache-like use cases we roll our own dictionary and it would be nice to not have to do that. |
benaadams commentedSep 7, 2020
runtime (Libraries Test Run release coreclr Windows_NT x86 Release) issue#41494 |
benaadams commentedSep 7, 2020
Helix gateway timeout on "runtime (Libraries Test Run release coreclr Windows_NT x86 Release)" |
3a519d8 to9c6de72Comparebenaadams commentedSep 8, 2020
Broken compress variant, but I'm quite impressed there are tests for these scenarios :) |
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
0eea740 to36abff2Comparesrc/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
387ec43 todc6f15eComparesrc/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
jkotas commentedSep 8, 2020
It would be nice to share performance numbers for the different cases. |
danmoseley commentedSep 8, 2020
@mjsabby the copy constructor specifically? It would be easy to add if someone would offer a PR. I am unsure what to do with DictionarySlim. It's encouraging that you're using it, or plan to. That may suggest we should remove the "Experimental" or even put it into the core collections. But@GrabYourPitchforks had concerns about it's "unsafeness" (I think related to mutating the entry in place). Also the name may suggest to people it's optimized for small number of items, which it's not (I happened to just run across@benaadamstype with the same name) |
GrabYourPitchforks commentedSep 11, 2020
The code LGTM. But we don't have evidence that this is a hot path for anybody. I'm somewhat paranoid that we're going to use this code as a new performance profile, then in the future we'll discover some obscure edge case which means we need to go down a somewhat slower path, then some automated system will kick in and say "Ah, but you regressed this method's performance by 17%!", and then we'll spend days chasing it down - all while continuing not to have evidence that this is actually a hot path for real-world apps. Basically, I'm afraid that it's signing us up for continuing maintenance work for a code path that we didn't want to invest significant resources into. |
benaadams commentedSep 11, 2020
Signals Rosyln would move away from ImmuntableDictionary for a fast Dictionary clone methoddotnet/roslyn#47503 (comment)
/cc@sharwell and
Also for lockless read Dictionary, with very infrequent updates (where reallocating the entire dictionary is more lightweight than taking a lock on every read, or using classLookupTable{privateDictionary<int,string>?_lookUp;privatereadonlyobject_lock=new();publicboolTryGetValue(intkey,[MaybeNullWhen(false)]outstringvalue){// No locks required for readvarlookUp=_lookUp;if(lookUpisnull){value=default;returnfalse;}returnlookUp.TryGetValue(key,outvalue);}publicvoidAdd(intkey,stringvalue){lock(_lock){// Clone + Addvardict=_lookUp?.Clone()??new(capacity:1);dict.Add(key,value);// Switch reference_lookUp=dict;}}publicvoidAddRange(IEnumerable<KeyValuePair<int,string>>collection){lock(_lock){// Clone + Addvardict=_lookUp?.Clone()??new(capacity:8);foreach(varentryincollection){dict.Add(entry.Key,entry.Value);}// Switch reference_lookUp=dict;}}} |
benaadams commentedSep 11, 2020
Its also why I wanted to add a clone extension method in#41939 publicstaticclassDictionaryExtensions{publicstaticDictionary<TKey,TValue>Clone<TKey,TValue>(thisDictionary<TKey,TValue>source)whereTKey:notnull{returnnewDictionary<TKey,TValue>(source,source.Comparer);}} Because it's not clear that passing a |
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
48eba29 to3121db3Comparesrc/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
eba83bc tob8a8d73Comparesrc/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
benaadams commentedSep 14, 2020
Released |
jkotas commentedSep 14, 2020
Nice! |
jkotas left a comment
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.
LGTM. Thanks!
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
eiriktsarpalis commentedSep 30, 2020
Is there any pending feedback on this PR? If not I'll just merge. |
benaadams commentedSep 30, 2020
Don't think so; CI wasn't behaving (one job failed in unrelated area), when it was was going to rebase for a clean set of greens, but looking at the open PRs doesn't look like CI is there yet... |
a963341 to3c2c6c4Comparebenaadams commentedOct 13, 2020
Squashed and Rebased |
eiriktsarpalis commentedOct 13, 2020
Failing tests seem like unrelated timeouts. |
eiriktsarpalis commentedOct 13, 2020
Thanks@benaadams! |
benaadams commentedOct 14, 2020
Aside it should also improve runtime/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/SparseTensor.cs Lines 108 to 112 inedb9019
runtime/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/SparseTensor.cs Lines 156 to 160 inedb9019
|
DrewScoggins commentedOct 16, 2020
Just wanted to update that we are seeing these wins in the performance lab for both strings and ints. Run Information
Regressions in System.Collections.CtorFromCollection
Reprogit clone https://github.com/dotnet/performance.gitpy .\performance\scripts\benchmarks_ci.py -f netcoreapp5.0 --filter 'System.Collections.CtorFromCollection<String>*' HistogramSystem.Collections.CtorFromCollection.Dictionary(Size: 512)DocsProfiling workflow for dotnet/runtime repository Run Information
Regressions in System.Collections.CtorFromCollection
Reprogit clone https://github.com/dotnet/performance.gitpy .\performance\scripts\benchmarks_ci.py -f netcoreapp5.0 --filter 'System.Collections.CtorFromCollection<Int32>*' HistogramSystem.Collections.CtorFromCollection.Dictionary(Size: 512)DocsProfiling workflow for dotnet/runtime repository |
danmoseley commentedOct 16, 2020
Love it - thank you@DrewScoggins for following up with that positive data. |
_1.png&f=jpg&w=240)
_1.png&f=jpg&w=240)
Uh oh!
There was an error while loading.Please reload this page.
Resolves#41939
Fast
.Clone()extension method can be made on top of this change asString keys are the biggest improvement since they cost most to rehash
https://github.com/dotnet/performance/compare/master...benaadams:DictionaryClone?expand=1