我运行了以下控制台应用程序:
class Program
{
static void Main(string[] args)
{
int n = 10000;
Stopwatch s = new Stopwatch();
s.Start();
List<int> numbers = GetListNumber(n);
foreach (var number in numbers)
{
}
s.Stop();
Console.WriteLine(s.Elapsed);
Console.WriteLine();
s.Restart();
foreach (var number in GetEnumerator(n))
{
}
s.Stop();
Console.WriteLine(s.Elapsed);
Console.ReadKey();
}
static List<int> GetListNumber(int n)
{
List<int> numbers = new List<int>();
for (int i = 0; i < n; i++)
numbers.Add(i);
return numbers;
}
static IEnumerable<int> GetEnumerator(int n)
{
for (int i = 0; i < n; i++)
yield return i;
}
}
Run Code Online (Sandbox Code Playgroud)
为了比较我们需要迭代集合元素的时间,以及是否更好地使用a List或a构建此集合IEnumerable.令我惊讶的是,结果是00:00:00.0005504 List和00:00:00.0016900 IEnumerable.我期待第二种方式,IEnumerable它会更快,因为值是动态创建的,我们不必每次都添加一个项目,就像a的情况一样List,然后迭代它.
可以请有人解释我这个区别吗?为什么我们得到这种行为,而不是相反的行为.
在此先感谢您的帮助!
首先,您的测试方式并不能真正给您提供有关性能差异的有用印象。10000 个项目的迭代确实太短了;您已经可以看到这一点,因为您可以在微秒内得到结果。相反,你应该始终尝试从中获得几秒钟的时间。此外,您应该始终按顺序多次运行相同的测试,然后取出平均值。这样您就可以消除随机影响并获得更稳定的结果(另请参阅大数定律)。
\n\n但是,迭代生成器函数可能会比列表慢。这是出于不同的原因:首先,当您从暂停执行的函数中获取项目时,实际上最终会进行大量上下文切换。I\xe2\x80\x99m 不确定这对于生成器函数来说是如何优化的,但你仍然必须以某种方式处理它们,所以你确实会受到惩罚。
\n\n其次,列出内部使用的数组,这些数组会根据需要动态调整大小。因此,最终,当您迭代列表时,您实际上是在迭代数组。您正在迭代内存中的一系列数字。这永远比其他任何事情都快。
\n\n最大的区别是内存方面,这应该让您考虑生成器函数而不是完整的列表。创建列表时,您将快速生成所有项目,将它们放入内存中,然后再次快速迭代它们。但你也把它们都记进了记忆里。因此,根据物品的数量,这可能意味着很大的成本。特别是当您只需要访问某个项目一次时,\xe2\x80\x99s 通常不值得。另一方面,生成器函数只需要单个项目的内存,因此从内存角度来看,这是非常高效的。
\n\n最后,虽然存在速度差异,但这可能永远不会有太大影响。\xe2\x80\x99 很少有应用程序会因为您决定在某处使用生成器函数而变慢。更有可能的是,您的应用程序的瓶颈位于其他地方,最有可能在 I/O 或网络操作中,因此您确实不应该关心它,直到它成为问题为止。
\n| 归档时间: |
|
| 查看次数: |
360 次 |
| 最近记录: |