Is 'yield return' slower than “old school” return?

后端 未结 5 1479
滥情空心
滥情空心 2020-12-19 10:01

I\'m doing some tests about yield return perfomance, and I found that it is slower than normal return.

I tested value variables (int, double, etc.) and some referenc

相关标签:
5条回答
  • 2020-12-19 10:34

    Because C# compiler converts iterator blocks (yield return) into state machine. State machine is very expensive in this case.

    You can read more here: http://csharpindepth.com/articles/chapter6/iteratorblockimplementation.aspx

    0 讨论(0)
  • 2020-12-19 10:37

    For one, it's a convenience feature. Two, it lets you do lazy return, which means that it's only evaluated when the value's fetched. That can be invaluable in stuff like a DB query, or just a collection you don't want to completely iterate over. Three, it can be faster in some scenarios. Four, what was the difference? Probably tiny, so micro optimization.

    0 讨论(0)
  • The .ToList() while necessary to really completing the otherwise deferred iteration of IEnumerable, hinders of measuring the core part.

    At least it is important of initializing the list to the known size:

    const int listSize=2000000; var tempList = new List(listSize);

    ...

    List tempList = YieldReturnTest(listSize).ToList();

    Remark: Both calls took about the same time on my machine.. No difference (Mono 4 on repl.it).

    0 讨论(0)
  • 2020-12-19 10:50

    Consider the difference between File.ReadAllLines and File.ReadLines.

    ReadAllLines loads all of the lines into memory and returns a string[]. All well and good if the file is small. If the file is larger than will fit in memory, you'll run out of memory.

    ReadLines, on the other hand, uses yield return to return one line at a time. With it, you can read any size file. It doesn't load the whole file into memory.

    Say you wanted to find the first line that contains the word "foo", and then exit. Using ReadAllLines, you'd have to read the entire file into memory, even if "foo" occurs on the first line. With ReadLines, you only read one line. Which one would be faster?

    That's not the only reason. Consider a program that reads a file and processes each line. Using File.ReadAllLines, you end up with:

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

    The time it takes that program to execute is equal to the time it takes to read the file, plus time to process the lines. Imagine that the processing takes so long that you want to speed it up with multiple threads. So you do something like:

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

    But the reading is single-threaded. Your multiple threads can't start until the main thread has loaded the entire file.

    With ReadLines, though, you can do something like:

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

    That starts up multiple threads immediately, which are processing at the same time that other lines are being read. So the reading time is overlapped with the processing time, meaning that your program will execute faster.

    I show my examples using files because it's easier to demonstrate the concepts that way, but the same holds true for in-memory collections. Using yield return will use less memory and is potentially faster, especially when calling methods that only need to look at part of the collection (Enumerable.Any, Enumerable.First, etc.).

    0 讨论(0)
  • 2020-12-19 10:53

    I used yield return to give me results from an algorithm. Every result is based on previous result, but I don't need all all of them. I used foreach with yield return to inspect each result and break the foreach loop if I get a result meet my requirement.

    The algorithm was decent complex, so I think there was some decent work involved for saving states between each yield returns.

    I noticed it was 3%-5% percentage slower than traditional return, but the improvement I get form not needing to generate all results is much much bigger than the loss of performance.

    0 讨论(0)
提交回复
热议问题