【发布时间】:2014-09-07 05:41:39
【问题描述】:
从 NuGet 包 Microsoft.Bcl.Immutable 版本 1.0.34 和 1.1.22-beta 中体验 Microsoft ImmutableList 的一些意外性能
从不可变列表中删除项目时,性能非常缓慢。
对于包含 20000 个整数值 (1...20000) 的 ImmutableList,如果开始从值 20000 删除到 1,则从列表中删除所有项目大约需要 52 秒。
如果我对通用 List<T> 执行相同操作,我会在每次删除操作后创建列表的副本,大约需要 500 毫秒。
我对这些结果有点惊讶,因为我认为 ImmutableList 会比复制通用 List<T> 更快,但也许这是意料之中的?
示例代码
// Generic List Test
var genericList = new List<int>();
var sw = Stopwatch.StartNew();
for (int i = 0; i < 20000; i++)
{
genericList.Add(i);
genericList = new List<int>(genericList);
}
sw.Stop();
Console.WriteLine("Add duration for List<T>: " + sw.ElapsedMilliseconds);
IList<int> completeList = new List<int>(genericList);
sw.Restart();
// Remove from 20000 -> 0.
for (int i = completeList.Count - 1; i >= 0; i--)
{
genericList.Remove(completeList[i]);
genericList = new List<int>(genericList);
}
sw.Stop();
Console.WriteLine("Remove duration for List<T>: " + sw.ElapsedMilliseconds);
Console.WriteLine("Items after remove for List<T>: " + genericList.Count);
// ImmutableList Test
var immutableList = ImmutableList<int>.Empty;
sw.Restart();
for (int i = 0; i < 20000; i++)
{
immutableList = immutableList.Add(i);
}
sw.Stop();
Console.WriteLine("Add duration for ImmutableList<T>: " + sw.ElapsedMilliseconds);
sw.Restart();
// Remove from 20000 -> 0.
for (int i = completeList.Count - 1; i >= 0; i--)
{
immutableList = immutableList.Remove(completeList[i]);
}
sw.Stop();
Console.WriteLine("Remove duration for ImmutableList<T>: " + sw.ElapsedMilliseconds);
Console.WriteLine("Items after remove for ImmutableList<T>: " + immutableList.Count);
更新
如果从 ImmutableList 的开头删除项目,就像使用普通的 foreach 循环一样,那么性能会好很多。删除所有项目只需不到 100 毫秒。
这不是您在所有情况下都可以做的事情,但很高兴知道。
【问题讨论】:
-
您是否尝试过使用
RemoveAt方法?见msdn.microsoft.com/en-us/library/dn456151.aspx -
我现在删除了 2 个答案,因为我误解了上面的代码和 ImmutableList 的实现。 @Servy 对 ImmutableList 的性质有一些有用的 cmets - “It's implemented as a binary search tree”,这些在我删除的帖子中丢失了。
-
没有尝试过
RemoveAt@KrisVandermotten,因为它在我的现实世界场景中没有用。可能会坚持使用旧的List<T>并结合使用锁定和快照,而不是使用ImmutableList<T>。 -
如果
RemoveAt在您的现实世界场景中没有用,那么此测试也不代表您的现实世界场景。您正在删除列表末尾的内容,这是一种特殊情况,恰好在可变列表中很快。
标签: c# performance immutability immutablelist