Skip to content

Comment on Decompiling C# (async/await)parent

Comments

A "yield return enumerable" is "delay executed" so evaluating it multiple times causes the yield-return execution to occur at every evaluation (if you haven't taken care to ToArray() or ToList() it). Do something like:

  var myBytes = GetMyBytesItr();
  for (var i = 0; i < myBytes.Count(); ++i)
  {
    ProcessByte(myBytes.ElementAt(i));
  }
and you'll be in a world of hurt especially if GetMyBytesItr() allocates a memory buffer. Count() causes the "get the bytes data" action to occur, as does every iteration of ElementAt(). Now I'm not saying this is definitely what you were experiencing, but it's a common pitfall. Also, using ElementAt() for each iteration is, of course, completely contrived for this example (you'd want to foreach instead which would cause only one execution of the "get the bytes data" action).

That wasn't the issue in my case. It was foreach (var b in f()). f did not do any allocations, just a loop with a bunch of yield return statements.

This is why I suspected that it was simply worse machine code after JIT. But I wasn't sure of all the details of the code that was inserted on my behalf.

One of the biggest differences is that if you do:

  foreach (var byte in byteArray)
The compiler transforms that into a normal for-loop that accesses the array directly. So that's already an advantage for the array over your enumerator.

The other difference that will have a major performance impact is the way the IEnumerator pattern works, even with generics. For:

  foreach (var b in f())
The generated code looks roughly like this:
  using (var enumerator = f())
  while (enumerator.MoveNext()) {
    var byte = enumerator.get_Current();
  }
As a result, you've gone from 0 method calls per iteration (direct array access) to 2 virtual method calls per iteration (MoveNext and get_Current). An incredibly smart JIT might be able to figure out that the virtual methods are always the same and turn them into static invocations, or even inline them, but I don't think the CLR can do this for you reliably.
AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.