提高IEnumerable.ToDictionary()的性能

时间:2018-02-07 08:02:46

标签: .net performance linq dictionary ienumerable

背景

我读了一个XML文件,并将一个巨大的(1百万)Person集合加载到内存中。此集合为IEnumerable(Of Person)

Public Class Person
    Public Property FirstName As String
    Public Property LastName As String
    Public Property Age As Int
End Class

我有什么

我想按FirstName对此集合进行分类,因此我写了这个Linq查询:

Dim groupedCollection = From p 
                         In Persons 
                        Group By p.FirstName
                         Into PersonsWithSameName = Group

现在我想将此groupedCollection转换为Dictionary。所以我写这个:

Dim myPersonDictionary = groupedCollection.ToDictionary(Function(x) x.FirstName, 
                                                        Function(x) x.PersonsWithSameName)

问题

问题在于.ToDictionary功能的表现对于这么大的收藏来说是可怕的。我不确定,但我认为这是因为它首先列举了我的原始集合,因为我将所有集合从开头到结尾都保留为IEnumerable,除了我需要枚举的情况。

我已阅读here,将Group By.ToDictionary放在一起并不是一个好主意。但是,当我使用建议的appraoch时,我看不出有什么区别(因此,首先在我的Select上执行groupedCollection)。

我想要实现的内容Dictionary(Of String, IEnumerable(Of Person))(或者我可以以类似方式使用的其他数据结构)。

我的问题是,我如何以更好的方式(在效果方面)获得此Dictionary

1 个答案:

答案 0 :(得分:0)

加载XML时很可能出现问题。

这是一个显示原因的例子:

var rnd = new Random();

Func<string> createName =
    () => new string(
        Enumerable
            .Range(0, 3)
            .Select(n => (char)(rnd.Next(0, 26) + 'a'))
            .ToArray());

var sw = Stopwatch.StartNew();

var persons =
    Enumerable
        .Range(0, 1000000)
        .Select(x => new { FirstName = createName(), LastName = createName() })
        .ToArray();

var el1 = sw.Elapsed;

var grouped = persons.GroupBy(p => p.FirstName, p => p.LastName).ToArray();

var el2 = sw.Elapsed;

var dictionary = grouped.ToDictionary(p => p.Key, p => p);

var el3 = sw.Elapsed;

Console.WriteLine(el1.TotalMilliseconds);
Console.WriteLine(el2.Subtract(el1).TotalMilliseconds);
Console.WriteLine(el3.Subtract(el2).TotalMilliseconds);

当我运行此代码时,我得到一个这样的输出:

1095.7095
266.2265
1.624

所以它需要1095.7095毫秒才能创建对象。然后需要266.2265将它们按名字分组。最后创建字典只需要1.624毫秒。

如果您遇到性能问题,那么它不在分组或创建字典中。否则,您需要发布您的代码并告诉我们您如何确定问题所在。