The cost of abstraction
Sasha commented on my perf post, and he mentioned the following:
But what if you're designing a messaging infrastructure for intra-application communication? It is no longer fine to hide it behind a mockable IQueue interface because that interface call is more expensive than the enqueue operation!
Now, I know that an interface call is more expensive than a non virtual call. The machine needs to do more work. But exactly how much more work is there to do? I decided to find out.
class Program
{
public static void Main(string[] args)
{
//warm up
PerformOp(new List<string>(101));
List<long> times = new List<long>();
Stopwatch startNew = new Stopwatch();
for (int i = 0; i < 50; i++)
{
startNew.Start();
PerformOp(new List<string>(101));
times.Add(startNew.ElapsedMilliseconds);
startNew.Reset();
}
Console.WriteLine(times.Average());
}
private static void PerformOp(IList<string> strings)
{
for (int i = 0; i < 100000000; i++)
{
strings.Add("item");
if(strings.Count>100)
strings.Clear();
}
}
}
I run this program with first with PerforOp(List<string>) and then with PerformOp(IList<string>). In the first case, we are doing non virtual method call, and in the second, we are going through the interface.
Running this has produced the following results:
- IList<T> - 2786 milliseconds
- List<T> - 2380 milliseconds
Well, that is a significant, right?
Not really. Remember that we run a tight loop of a hundred million times.
Let us see individual call times:
- IList<T> - 0.0000278600 milliseconds
- List<T> - 0.0000238000 milliseconds
The difference between the two is 0.00000406 milliseconds. In other words, it is an insignificant part of a microsecond.
The difference between a non virtual call and an method call is significantly less than a microsecond.
I don't think that I am going to worry about that, thank you very much.