-
Notifications
You must be signed in to change notification settings - Fork 5k
Improve performance of Enumerable.ToDictionary()
#96574
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve performance of Enumerable.ToDictionary()
#96574
Conversation
Tagging subscribers to this area: @dotnet/area-system-linq Issue DetailsSummaryIn this Pull-Request, I've improved the performance of the
Benchmark
public class ToDictionaryBenchmark
{
private const int Length = 10000;
private static readonly IEnumerable<Kvs> s_enumerable = Enumerable.Range(0, Length).Select(x => new Kvs(x, x));
private static readonly IEnumerable<Kvs> s_array = s_enumerable.ToArray();
private static readonly IEnumerable<Kvs> s_list = s_enumerable.ToList();
[Benchmark(Baseline = true)]
public Dictionary<int, Kvs> EnumerableToDictionary()
=> s_enumerable.ToDictionary(static x => x.Key);
[Benchmark]
public Dictionary<int, Kvs> ArrayToDictionary()
=> s_array.ToDictionary(static x => x.Key);
[Benchmark]
public Dictionary<int, Kvs> ListToDictionary()
=> s_list.ToDictionary(static x => x.Key);
[Benchmark]
public Dictionary<int, Kvs> PR_EnumerableToDictionary()
=> s_enumerable.ToDictionary_PR(static x => x.Key);
[Benchmark]
public Dictionary<int, Kvs> PR_ArrayToDictionary()
=> s_array.ToDictionary_PR(static x => x.Key);
[Benchmark]
public Dictionary<int, Kvs> PR_ListToDictionary()
=> s_list.ToDictionary_PR(static x => x.Key);
}
public record struct Kvs(int Key, int Value);
|
@dotnet-policy-service agree |
Thanks. What does the comparison look like, in particular for an iterator that conveys no size information, with a small length, like 3? |
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.
@stephentoub
※ This is due to the increased type determination in Whether or not this overhead is considered negligible compared to the benefits gained from setting the initial capacity, I believe, is the determining factor in whether or not to incorporate this Pull-Request. Although you have already approved, I will document the measurement results just in case. Benchmark
public class ToDictionaryBenchmark
{
private static readonly IEnumerable<Kvs> s_enumerable = EnumerateSample();
private static readonly IEnumerable<Kvs> s_array = s_enumerable.ToArray();
private static readonly IEnumerable<Kvs> s_list = s_enumerable.ToList();
private static IEnumerable<Kvs> EnumerateSample()
{
for (var i = 0; i < 3; i++)
yield return new Kvs(i, i);
}
[Benchmark(Baseline = true)]
public Dictionary<int, Kvs> EnumerableToDictionary()
=> s_enumerable.ToDictionary(static x => x.Key);
[Benchmark]
public Dictionary<int, Kvs> ArrayToDictionary()
=> s_array.ToDictionary(static x => x.Key);
[Benchmark]
public Dictionary<int, Kvs> ListToDictionary()
=> s_list.ToDictionary(static x => x.Key);
[Benchmark]
public Dictionary<int, Kvs> PR_EnumerableToDictionary()
=> s_enumerable.ToDictionary2(static x => x.Key);
[Benchmark]
public Dictionary<int, Kvs> PR_ArrayToDictionary()
=> s_array.ToDictionary2(static x => x.Key);
[Benchmark]
public Dictionary<int, Kvs> PR_ListToDictionary()
=> s_list.ToDictionary2(static x => x.Key);
}
public record struct Kvs(int Key, int Value); |
Thanks for the numbers. A ns on an extreme case is reasonable. |
Summary
In this Pull-Request, I've improved the performance of the
Enumerable.ToDictionary()
method in the following two points.ICollection
orIIListProvider<T>
T[]
andList<T>
into a specialization forReadOnlySpan<T>
List<T>
Benchmark