我正在做一些关于收益率回归性能的测试,我发现它比正常回报慢.
我测试了值变量(int,double等)和一些引用类型(字符串等)......并且两种情况下的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);
}
}
Run Code Online (Sandbox Code Playgroud)
Jim*_*hel 12
考虑之间的差异File.ReadAllLines和File.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
}
Run Code Online (Sandbox Code Playgroud)
程序执行所花费的时间等于读取文件所需的时间,加上处理行的时间.想象一下,处理需要很长时间,以至于你想用多个线程来加速它.所以你做的事情如下:
lines = File.ReadAllLines(filename);
Parallel.Foreach(...);
Run Code Online (Sandbox Code Playgroud)
但阅读是单线程的.在主线程加载整个文件之前,您的多个线程无法启动.
有了ReadLines,不过,你可以这样做:
Parallel.Foreach(File.ReadLines(filename), line => { ProcessLine(line); });
Run Code Online (Sandbox Code Playgroud)
这会立即启动多个线程,这些线程在读取其他线路的同时进行处理.因此,读取时间与处理时间重叠,这意味着您的程序将更快地执行.
我使用文件展示我的示例,因为它更容易以这种方式演示概念,但对于内存中的集合也是如此.使用yield return将使用较少的内存,并可能更快,称只需要看看集合的一部分(尤其是方法的时候Enumerable.Any,Enumerable.First等).