Mri*_*msh 62 .net collections optimization performance list
我的代码中有一些通用列表,有几十或几百个元素.有时候我需要用其他对象重新填充这个列表,所以问题是:什么会更快,调用Clear()
方法或创建new List<T>()
?
Ree*_*sey 58
什么会更快,调用
Clear()
方法或创建一个新的List()?
这是不可能回答的.这实际上取决于很多因素,包括收集存在多长时间.
这里最好的选择是:
描述应用程序,看看这是否真的重要.它可能不会产生任何可察觉的差异,在这种情况下,我会使用最能理解这个对象的方法.
如果确实重要,请编写两组代码,并测量速度差异(如果有的话).
从实际角度来看,调用Clear()
实际上不会减少内存(由List<T>
自身使用),因为它不会缩小列表的容量,只会消除其中包含的值.创建新的List<T>
将导致分配新列表,这反过来会导致更多的分配增长.
然而,这并不意味着它会变慢 - 在许多情况下,重新分配将更快,因为您不太可能将大型阵列推广到更高的垃圾收集代,这反过来可以更快地保持GC过程.
不知道您的具体情况,并测量在探查,也没有办法知道这是您的方案更好.
ast*_*tef 22
我运行了这个测试:
private static void Main(string[] args)
{
int defaultN = 1000;
Stopwatch sw = new Stopwatch();
while (true)
{
Console.WriteLine("Enter test elements number:");
int n;
if (!int.TryParse(Console.ReadLine(), out n)) n = defaultN;
else defaultN = n;
Console.WriteLine($"Test with {n} elements");
List<object> list = Enumerable.Repeat(new object(), n).ToList();
sw.Start();
Clear(list);
sw.Stop();
Console.WriteLine("Clear: {0} ms", sw.ElapsedTicks / 10000D);
GC.Collect();
GC.WaitForPendingFinalizers();
List<object> list2 = Enumerable.Repeat(new object(), n).ToList();
sw.Restart();
Reinitialize(list2);
sw.Stop();
Console.WriteLine("Reinitialize: {0} ms", sw.ElapsedTicks / 10000D);
GC.Collect();
GC.WaitForPendingFinalizers();
List<object> list3 = Enumerable.Repeat(new object(), n).ToList();
sw.Restart();
ReinitializeAndCollect(list3);
sw.Stop();
Console.WriteLine("ReinitializeAndCollect: {0} ms", sw.ElapsedTicks / 10000D);
Console.WriteLine("===");
}
}
private static List<object> Clear(List<object> list)
{
list.Clear();
return list;
}
private static List<object> Reinitialize(List<object> list) => new List<object>();
private static List<object> ReinitializeAndCollect(List<object> list)
{
list = new List<object>();
GC.Collect();
GC.WaitForPendingFinalizers();
return list;
}
Run Code Online (Sandbox Code Playgroud)
我的结论基于我的普通核心i3处理器的结果:
如果有数千个元素 - 最好清除列表.它速度快,内存效率高.
如果收集有超过10万个元素 - 重新初始化变得更具吸引力.如果在分析后你认为这里存在瓶颈,请使用它.重新初始化将非常快,但正如第三种方法测试所示,未来的垃圾收集将与清除列表一样慢.
如此简短的回答是:如果您没有分析您的应用程序,请使用Clear
.重用对象很好.如果你这样做 - 你已经知道该怎么做了.
Clear()
将删除所有元素,并保持现有容量,而创建一个新列表将需要从托管堆中至少进行一次分配(如果初始容量较小,则随着项目的添加可能会更多)。
如果您有大量项目,并且每次迭代的项目数量大致相同,则使用Clear
可能会稍快一些。
如果一次迭代中的项目数量特别多,而后续迭代中的项目数量要少得多,那么使用的Clear
成本可能会更高,因为您将在内存中保留一个具有不必要的大容量的列表。
当然,在许多(大多数?)场景中,差异可以忽略不计。
也许我在这里做了一些根本性的错误,但是在使用 C# 开发 ASP.NET 应用程序时,我在使用 Clear() 与 new 时遇到了很大的差异。我正在创建一个带有图表的统计页面,其中包含数据系列。对于每个图表,我都有一个部分来执行此操作:
chart = new ChartistChart() { Title = "My fancy chart" };
series = new List<ChartistMetaValue>();
*some code for getting the statistics*
chart.Series.Add(series);
chartistLineCharts.Add(chart);
Run Code Online (Sandbox Code Playgroud)
然后是另一张图表。
chart = new ChartistChart() { Title = "My second fancy chart" };
series = new List<ChartistMetaValue>();
*some code for getting the statistics*
chart.Series.Add(series);
chartistLineCharts.Add(chart);
Run Code Online (Sandbox Code Playgroud)
series
这对于重新分配来说效果很好new
,但是当我这样做时
series.Clear();
Run Code Online (Sandbox Code Playgroud)
相反,我实际上清除了内部条目chart.Series
,chartistLineCharts
因此统计页面最终仅检索最后一个图表的系列。我假设这里存在一些链接,例如内存指针,这是与最初讨论的问题不同的问题,但这至少是new
选择Clear()
. 也许有一种方法可以避免它。
我自己做了几次测试。结果(速度)是:
但最终,最好分析应用程序并找到整个应用程序的瓶颈。
归档时间: |
|
查看次数: |
27013 次 |
最近记录: |