Why doesn't C# have an 'inline' keyword?
I got this question in email today, and I thought I'd share my response.
For those of you who don't know, the 'inline' keyword in the C language was designed to control whether the compiler inlined a function into the calling function. For example, if I had something like
int square(int x)
{
return x * x;
}
and used it here:
int y = square(x);
I would be making a function call for a single expression, which would be pretty inefficient. Adding “inline' to the definition would tell the compiler to inline it, effectively changing my use to:
int y = x * x;
and giving me the abstract of a function call without the overhead.
Inline had some good uses in early C compilers, but it was also prone to misuse - some programmers would decorate all their functions with 'inline', which would give them no function calls, very big code, and therefore slow execution.
That led to the next phase, where programmers would only put 'inline' on functions where they needed the performance. That kept the code smaller, but missed cases like the one I have above where the inlined code is smaller than the function call code, where you want to inline every time. These cases only got caught if the programmer noticed them.
Finally, as systems got better, compilers got into the act, and started doing enough analysis to make good decisions on their own without 'inline' keyword. In fact, the compiler writers discovered that the heuristics that they put in the compiler made better choices than programmers did, and some compilers started ignoring 'inline' and just doing what they thought best. This was legal because inline was always defined as a hint, not a requirement.
This worked really well for most cases, but there were some cases where the programmer really wanted something to be inline (ie override the heuristics). This was sometimes around as a request for the “inlinedammit!“ keyword, which showed up in VC++ in V6.0 (IIRC) as the nicer named “__forceinline“.
So how does that relate to C#? Well, it doesn't, but it's an interesting story so I wanted to share it with you.
For C#, inlining happens at the JIT level, and the JIT generally makes a decent decision. Rather than provide the ability to override that, I think the real long-term solution is to use profile-guided feedback so that the JIT can be smarter about what it inlines and what it doesn't.
Comments
Anonymous
January 29, 2004
Here's a related question.
When you create a property in .NET, we create it something like this.
private int _num;
public int TheNumber
{
get { return this.num; }
set { this.num = value; }
}
The compiler will create the appropriate get and set accessor functions.
My question is this.
If you are creating, say... a control, and using your properties internally, is it
more effecient to use the private member variable, or to call the property explicitly? Basically, should
you do ....
int temp = this.TheNumber
or....
int temp = this._num;
This is assuming that the getter function is just returning the value of the private member. If additional logic was needed, then of course you would call the accessor. But if you're just returning a simple value, I would think you could skip the overhead of calling the function. I doubt it would save much on 1 or 2 calls, but I've seen code similar to this many times.
for ( int i = 0; i != 1000; i++ )
{
if ( this.TheNumber > 8 )
// do something
}
In the above example, there would be a 1000 calls to the accessor function, which seems less effecient than 1000 calls to just check the value of a variable.
Encapsulation wise, it is far better to call the property directly, but is it better performance wise to call the private member directly?
I know there is no simple answer, but I'm curious as to whether or not the compiler helps out here.Anonymous
January 29, 2004
My desires are a bit more simplistic - I've just always wished C# would have something similar to VB.NET's "With" keyword. :)Anonymous
January 29, 2004
Several years ago our software group had the same discussion about inline functions. The senior developers made the same point that the compiler does a better job at optimizing. Actually between the compiler and the CPU instruction pipeline optimizations, its a non-trivial issue to understand. We told the gungho performance geeks that we wouldn't accept inline but if they were serious they could write asm blocks. Funny how none of the performance people took us up on the offer.Anonymous
January 29, 2004
What would happen in VC++ with:
__forceinline void Factorial(int x)
{
if (x == 1)
return 1;
else
return x * Factorial(x-1); }
}
??? ;-)Anonymous
January 29, 2004
Scott,
Human sacrifices, dogs and cats living together! Mass hysteria!Anonymous
February 04, 2004
The comment has been removedAnonymous
February 04, 2004
The comment has been removedAnonymous
February 04, 2004
JIT Inlining, is this set in stone on the first JIT or can it rejit if it realises its better inlined based on usage during runtime?
If not would this be implemented in future? Obviously you dont want it to spend alot of time reJITting a method to inline or not inline based on profiling data if its oscilating about.Anonymous
February 04, 2004
The world MIGHT end and planets MAY collide.
# re: Why doesn't C# have an 'inline' keyword? 1/29/2004 9:24 PM Scott Mitchell
What would happen in VC++ with:
__forceinline void Factorial(int x)
{
if (x == 1)
return 1;
else
return x * Factorial(x-1); }
}
??? ;-)Anonymous
February 05, 2004
Also, the code was faulty since factorial is defined for n >= 0 and for 0!=1 by definition. (could be calculated too.)
n! = n*(n-1)! for n > 1
Therefore it should have been...
__forceinline void Factorial(int x)
{
if (x < 1)
return 1;
else
return x * Factorial(x-1); }
}Anonymous
April 25, 2004
Adnan, the original Factorial() author's real question was "What happens with __forceinline and recursive fcns?", not "Does this code implement factorial right?"
Since you needlessly picked on someone else's pseudo code snippet, I'll pick on yours:
Your fix is only partial -- you still quietly give an incorrect answer for negatives, you don't detect overflow and you return void!
Of course the best implementation of Factorial, as you noted, is to just have an array of the first 20 pre-computed, 64 bit answers and use the argument as the offset.Anonymous
December 18, 2004
Helpful For MBA Fans.Anonymous
June 01, 2008
.Net inlines everything it canAnonymous
August 19, 2008
PingBack from http://www.ademiller.com/blogs/tech/2008/08/c-inline-methods-and-optimization/Anonymous
June 07, 2009
PingBack from http://greenteafatburner.info/story.php?id=3567