The cost of abstraction

time to read 2 min | 309 words

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.