Friday, May 19, 2006

Cost of Calling Methods in C#

What does a method call cost in C#? Should I use temps to reduce method calls?


In university, so many years ago, we learned that one of the most performance intensive operations was the method call. The professor explained the work required to create a stack frame, and move values into it, etc. Well... that was then, when maybe compilers weren't quite so efficient. Is this still true? What is the overhead when calling a method with a modern language like C#?


Why do I care about this?


Martin Fowler in his book Refactoring: Improving the Design of Existing Code, (which I am currently re-reading) describes several method creation refactorings, one of which is driven by the desire to remove temporary variables from a method (Replace Temp with Query). The motivation behind this refactoring is based on the idea that temporary variables encourage large methods and make refactoring difficult. Upon reading this refactoring I recalled the university lecture where we discussed the cost of calling methods and use of the C++ inline keyword (inline is a C++ compiler hint to not actually create a function and call it, but to generate inline code instead). In C++ 'inline' exists because function calls can be expensive. So I created a simple test to measure the overhead with method calls.


Method Call Overhead Results


Here is the code I wrote to measure the method call overhead, one method that simply does a calculation inline, and another that calls a function to do the calculation.



public class MethodCallCost
{
private int _iterations;
private int _valueA;
private int _valueB;

public MethodCallCost(int iterations, int valueA, int valueB)
{
_iterations = iterations;
_valueA = valueA;
_valueB = valueB;
}
public void MethodCall()
{
double temp = 0;
for( int i = 1; i < _iterations; i++ )
{
temp = CalculateAmount(_valueA, _valueB, i);
}
}
private double CalculateAmount(int valueA, int valueB, int divisor)
{
int result = valueA * valueB / divisor;
return result;
}
public void Inline()
{
double temp = 0;
for( int i = 1; i < _iterations; i++ )
{
temp = _valueA * _valueB / i;
}
}
}


I created the MethodCallCost object to run 3,000,000 iterations. Here are some results,
































Method Call (Ms)Inline (Ms)
9347
11047
9363
9462
9462
9447
9462
9447
10963
7862

So, my conclusion (with this simple and perhaps insufficient test) is that method calls are cheap. The benefits of the 'Replace Temp with Query' are probably worth it. Now of course you may have a complex method that calls a webservice, or into a database, and in that case of course it probably makes sense the store the result instead of requerying. There are still judgement calls to be made, but go ahead and create method calls, just remember to profile and tune.

No comments:

Post a Comment