.net 哪个更快:清除集合还是实例化新集合
我的代码中有一些通用列表,它们有几十个或几百个元素。.net 哪个更快:清除集合还是实例化新集合,.net,performance,list,optimization,collections,.net,Performance,List,Optimization,Collections,我的代码中有一些通用列表,它们有几十个或几百个元素。 有时我需要用其他对象重新填充这个列表,所以问题是:调用Clear()方法或创建一个新列表()?虽然这可能会令人沮丧,但答案确实是这不重要。两者之间的时间差将非常小,可能不会对应用程序产生任何影响。做能让代码更清晰、更易懂的事情,尽量不要为微优化编程。如果对象是值类型,我会使用Clear()来减少未来的内存分配。否则,这两种方法几乎相同 调用Clear() 这是不可能回答的。这实际上取决于很多因素,包括收藏存在的时间 这里的最佳选择是: 分析应
有时我需要用其他对象重新填充这个列表,所以问题是:调用
Clear()
方法或创建一个新列表()
?虽然这可能会令人沮丧,但答案确实是这不重要。两者之间的时间差将非常小,可能不会对应用程序产生任何影响。做能让代码更清晰、更易懂的事情,尽量不要为微优化编程。如果对象是值类型,我会使用Clear()来减少未来的内存分配。否则,这两种方法几乎相同
调用Clear()
这是不可能回答的。这实际上取决于很多因素,包括收藏存在的时间
这里的最佳选择是:
分析应用程序,看看这是否真的很重要。它很可能不会产生任何明显的区别,在这种情况下,我会使用最有意义的方法来看待这个物体
如果有关系,编写两组代码,并测量速度差异(如果有)
从实际角度来看,调用Clear()
实际上不会减少内存(由列表本身使用),因为它不会收缩列表的容量,只会消除其中包含的值。创建一个新的列表
将导致分配一个新列表,这将随着增长而导致更多的分配
但是,这并不意味着它会更慢—在许多情况下,重新分配会更快,因为您不太可能将大型阵列升级到更高的垃圾收集代,这反过来又可以使GC进程更快
如果不知道您的确切场景并在探查器中进行测量,就无法知道在您的场景中哪一个更好。这将取决于许多因素,从长远来看,在您的程序中可能不重要(足以计算)
从msdn.Clear()
是一个O(n)操作
初始化一个新实例将有它自己的开销(如果保持集合的长度不变,则会有一个O(n)操作:即nAdd()
calls)
实际上,测试这一点的唯一方法是在你的程序中设置一些秒表,如果你真的认为值得的话,看看效果如何。极有可能;这不值得
我的想法是,如果您已经创建了一个集合,Clear()
it,这就是为什么首先会有一个Clear()
方法。Clear()
将删除所有元素,并保持现有容量,而创建一个新列表将至少需要从托管堆中分配一次(如果初始容量较小,可能会添加更多项)
- 如果您有大量项目,并且每次迭代的项目数量大致相同,那么使用
Clear
可能会稍微快一点
- 如果您在一次迭代中有非常多的项目,那么在后续迭代中的项目数量要小得多,那么使用
Clear
可能成本更高,因为您将在内存中保留一个容量不必要的列表
当然,在许多(大多数?)场景中,差异可以忽略不计。我已经运行了以下测试:
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;
}
private static void Main(字符串[]args)
{
int defaultN=1000;
秒表sw=新秒表();
while(true)
{
Console.WriteLine(“输入测试元素编号:”);
int n;
如果(!int.TryParse(Console.ReadLine(),out n))n=defaultN;
n=n;
WriteLine($“使用{n}个元素进行测试”);
List=Enumerable.Repeat(新对象(),n).ToList();
sw.Start();
清除(列表);
sw.Stop();
Console.WriteLine(“清除:{0}ms”,sw.ElapsedTicks/10000D);
GC.Collect();
GC.WaitForPendingFinalizers();
List list2=Enumerable.Repeat(new object(),n).ToList();
sw.Restart();
重新初始化(列表2);
sw.Stop();
Console.WriteLine(“重新初始化:{0}ms”,sw.ElapsedTicks/10000D);
GC.Collect();
GC.WaitForPendingFinalizers();
List list3=Enumerable.Repeat(新对象(),n).ToList();
sw.Restart();
重新初始化并收集(列表3);
sw.Stop();
WriteLine(“重新初始化并收集:{0}ms”,sw.ElapsedTicks/10000D);
Console.WriteLine(“=”);
}
}
专用静态列表清除(列表)
{
list.Clear();
退货清单;
}
私有静态列表重新初始化(列表)=>new List();
私有静态列表重新初始化并收集(列表列表)
{
列表=新列表();
GC.Collect();
GC.WaitForPendingFinalizers();
退货清单;
}
我的结论基于我的普通core i3处理器的结果:
如果有数千个元素,最好清除列表。它速度快,内存效率高
如果收集有超过100000个元素,则重新初始化会变得更吸引人。如果在分析之后您认为这里存在瓶颈,请使用它。重新初始化将非常快,但正如第三种方法测试所示,未来的垃圾收集将与清理列表一样慢
简而言之,答案是:如果你没有分析你的应用程序,请使用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);
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);
series.Clear();