gpt4 book ai didi

c# - 'yield return' 比 "old school"返回慢吗?

转载 作者:太空狗 更新时间:2023-10-30 00:03:04 25 4
gpt4 key购买 nike

我正在做一些关于 yield 返回性能的测试,我发现它比正常返回慢。

我测试了值变量(int、double 等)和一些引用类型(string 等)...并且在这两种情况下 yield return 都比较慢。那为什么要用它呢?

看看我的例子:

public class YieldReturnTeste
{
private static IEnumerable<string> YieldReturnTest(int limite)
{
for (int i = 0; i < limite; i++)
{
yield return i.ToString();
}
}

private static IEnumerable<string> NormalReturnTest(int limite)
{
List<string> listaInteiros = new List<string>();

for (int i = 0; i < limite; i++)
{
listaInteiros.Add(i.ToString());
}
return listaInteiros;
}

public static void executaTeste()
{
Stopwatch stopWatch = new Stopwatch();

stopWatch.Start();

List<string> minhaListaYield = YieldReturnTest(2000000).ToList();

stopWatch.Stop();

TimeSpan ts = stopWatch.Elapsed;


string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",

ts.Hours, ts.Minutes, ts.Seconds,

ts.Milliseconds / 10);

Console.WriteLine("Yield return: {0}", elapsedTime);

//****

stopWatch = new Stopwatch();

stopWatch.Start();

List<string> minhaListaNormal = NormalReturnTest(2000000).ToList();

stopWatch.Stop();

ts = stopWatch.Elapsed;


elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",

ts.Hours, ts.Minutes, ts.Seconds,

ts.Milliseconds / 10);

Console.WriteLine("Normal return: {0}", elapsedTime);
}
}

最佳答案

考虑 File.ReadAllLinesFile.ReadLines 之间的区别。

ReadAllLines 将所有行加载到内存中并返回一个 string[]。如果文件很小,一切都很好。如果文件大于内存中的容量,您将耗尽内存。

另一方面,

ReadLines 使用 yield return 一次返回一行。有了它,您可以读取任何大小的文件。它不会将整个文件加载到内存中。

假设您想找到包含单词“foo”的第一行,然后退出。使用 ReadAllLines,您必须将整个文件读入内存,即使“foo”出现在第一行也是如此。使用 ReadLines,您只需阅读一行。哪个会更快?

这不是唯一的原因。考虑一个读取文件并处理每一行的程序。使用 File.ReadAllLines,您最终得到:

string[] lines = File.ReadAllLines(filename);
for (int i = 0; i < lines.Length; ++i)
{
// process line
}

程序执行的时间等于读取文件的时间加上处理行的时间。想象一下,处理需要很长时间,以至于您想使用多个线程来加快处理速度。所以你做这样的事情:

lines = File.ReadAllLines(filename);
Parallel.Foreach(...);

但是读取是单线程的。在主线程加载整个文件之前,您的多个线程无法启动。

不过,使用 ReadLines,您可以执行以下操作:

Parallel.Foreach(File.ReadLines(filename), line => { ProcessLine(line); });

这会立即启动多个线程,这些线程在读取其他行的同时进行处理。因此读取时间与处理时间重叠,这意味着您的程序将执行得更快。

我使用文件展示我的示例,因为这样更容易演示概念,但内存中的集合也是如此。使用 yield return 将使用更少的内存并且可能更快,尤其是在调用只需要查看部分集合的方法时(Enumerable.AnyEnumerable.首先等)。

关于c# - 'yield return' 比 "old school"返回慢吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18145944/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com