In the previous "What's New for Parallelism in Visual Studio 2012 RC" blog post, I mentioned briefly that for the .NET 4.5 Release Candidate, StreamReader.ReadLineAsync experienced a significant performance improvement over Beta. There's an intriguing story behind that, one I thought I'd share here.
It has to do with some interesting interactions between certain optimizations in the BCL and how the C# and Visual Basic compilers compile async methods. Before I describe the changes made, a bit of experimentation will be useful to help set the stage.
Consider the following code. The code is simply timing how long it takes to run two different async methods (which don’t actually await anything, and so will run to completion synchronously). Each method increments an integer 100 million times. The first method does so by incrementing a field 100 million times, and the second method does so by copying the field into a local, incrementing that local 100 million times, and then storing the local back to the field.
using System;
using System.Diagnostics;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var sw = new Stopwatch();
var obj = new MyObj();
while (true)
{
foreach (var m in new Func<Task>[] {
new MyObj().Foo1, new MyObj().Foo2 })
{
sw.Restart();
m();
sw.Stop();
Console.WriteLine("{0}: {1}", m.Method.Name, sw.Elapsed);
}
Console.WriteLine();
}
}
}
class MyObj
{
const int ITERS = 100000000;
private int m_data;
public async Task Foo1()
{
for (int i = 0; i < ITERS; i++) m_data++;
}
Read more: Stephen Toub - MSFT
QR: