views:

1086

answers:

9

I'm writing an XNA game where I do per-pixel collision checks. The loop which checks this does so by shifting an int and bitwise ORing and is generally difficult to read and understand.

I would like to add private methods such as private bool IsTransparent(int pixelColorValue) to make the loop more readable, but I don't want the overhead of method calls since this is very performance sensitive code.

Is there a way to force the compiler to inline this call or will I do I just hope that the compiler will do this optimization?

If there isn't a way to force this, is there a way to check if the method was inlined, short of reading the disassembly? Will the method show up in reflection if it was inlined and no other callers exist?

Edit: I can't force it, so can I detect it?

A: 

Nope, you can't.

Basically, you can't do that in most modern C++ compilers either. inline is just an offer to the compiler. It's free to take it or not.

The C# compiler does not do any special inlining at the IL level. JIT optimizer is the one that will do it.

Mehrdad Afshari
"If there isn't a way to force this, is there a way to check if the method was inlined, short of reading the disassembly? Will the method show up in reflection if it was inlined and no other callers exist?"
Ben S
Nope, I doubt the C# compiler does any inlining at all. JIT compiler is responsible for that.
Mehrdad Afshari
You can check System.Reflection.MethodBase.GetCurrentMethod().Name. If the method is inlined, it will return the name of the caller instead.
Joel Coehoorn
And the compiler does occasionally inline a method.
Joel Coehoorn
Joel - you should submit that as an answer to the second part of his question.
Erik Forbes
Jeol: are you sure about that?
Mehrdad Afshari
Meh: thought about it, but I wouldn't have had a clue without reading this answer first. I have enough rep.
Joel Coehoorn
I posted it and attributed you, future readers won't have to look at comments to find the answer.
Ben S
@Mehrdad: Pretty sure. Learned about it here first, and several of the answers there brought up inlining as something to watch for: http://stackoverflow.com/questions/44153
Joel Coehoorn
The thing is, when we have reflection in place, the high level compiler should not alter how they are called. You might want to override a method in a class at runtime. If C# compiler inlined it, it wouldn't have been possible. I'm pretty sure of that but I can't be 100% certain.
Mehrdad Afshari
Good point about the optimizer being the culprit, but it still happens :)
Joel Coehoorn
@Meh: I believe inlining will only occur on non-virtual calls.
Mark Brackett
@Mark: by `overriding` I didn't mean virtual calls. I meant reprogramming a method dynamically by means of reflection.
Mehrdad Afshari
Disclaimer: While I haven't seen C# compiler doing any inlining and I think the JIT is responsible, it's still not a proof that C# doesn't do it at all. :)
Mehrdad Afshari
@Meh: I'll admit - that went over my head. I know of no way to "reprogram a method dynamically". But, as mentioned, the compiler does inline calls occasionally - so you'll need to watch out for it.
Mark Brackett
It is possible to reprogram a *dynamically emitted* method by means of `MethodRental.SwapMethodBody`. Well, it might not something that C# has to worry about since it has all the method calls routed to statically emitted methods, but it was just a thought :)
Mehrdad Afshari
@Meh: In the case of a dynamically emitted method, I'd assume there is no inlining (as there's no compiler - you're emitting MSIL, so you'd be in charge of inlining if you wanted) so you should be safe. Interesting thought, though - and perhaps something the dynamic languages have to worry about.
Mark Brackett
+5  A: 

"You can check System.Reflection.MethodBase.GetCurrentMethod().Name. If the method is inlined, it will return the name of the caller instead."

--Joel Coehoorn

Ben S
It will only work at runtime.
Alex Reitbort
Of course it will only work at runtime, that is when inlining occurs.
Jonathan Allen
Doesn't calling this method in your code change the actual IL, which would theoretically change the JIT compiler's 'reasoning' if it should be inlined or not?
Erik van Brakel
Yes. For one thing, that extra code could put you over the 32-byte inlining limit. So if the extra code indicates that it does get inlined, you know that it does. But if it indicates that it does not get inlined, you don't really know if it would have been without the extra code.
Fantius
+4  A: 

No you can't. Even more, the one who decides on inlining isn't VS compiler that takes you code and converts it into IL, but JIT compiler that takes IL and converts it to machine code. This is because only the JIT compiler knows enough about the processor architecture to decide if putting a method inline is appropriate as it’s a tradeoff between instruction pipelining and cache size.

So even looking in .NET Reflector will not help you.

Alex Reitbort
Others beg to differ about reflection since it uses the call stack. http://stackoverflow.com/questions/44153/can-you-use-reflection-to-find-the-name-of-the-currently-executing-method/44171#44171
Ben S
I didn't say reflection, I said reflector, as in Red Gates .NET Reflector.
Alex Reitbort
My bad, I misunderstood that.
Ben S
A: 

You can detect it at runtime with the aforementioned GetCurrentMethod call. But, that'd seem to be a bit of a waste[1]. The easiest thing to do would to just ILDASM the MSIL and check there.

Note that this is specifically for the compiler inlining the call, and is covered in the various Reflection docs on MSDN.

If the method that calls the GetCallingAssembly method is expanded inline by the compiler (that is, if the compiler inserts the function body into the emitted Microsoft intermediate language (MSIL), rather than emitting a function call), then the assembly returned by the GetCallingAssembly method is the assembly containing the inline code. This might be different from the assembly that contains the original method. To ensure that a method that calls the GetCallingAssembly method is not inlined by the compiler, you can apply the MethodImplAttribute attribute with MethodImplOptions.NoInlining.

However, the JITter is also free to inline calls - but I think a disassembler would be the only way to verify what is and isn't done at that level.

Edit: Just to clear up some confusion in this thread, csc.exe will inline MSIL calls - though the JITter will (probably) be more aggressive in it.

[1] And, by waste - I mean that (a) that it defeats the purpose of the inlining (better performance) because of the Reflection lookup. And (b), it'd probably change the inlining behavior so that it's no longer inlined anyway. And, before you think you can just turn it on Debug builds with an Assert or something - realize that it will not be inlined during Debug, but may be in Release.

Mark Brackett
Yep: it's definitely a waste to test this at runtime. If it was JIT'd inline, there was probably a _good_ reason for it, and this check will only make things worse. But I took this as more of a learning exercise: he want's to "experience" inlining for himself.
Joel Coehoorn
+1  A: 

why not use unsafe code (inline c as its known) and make use of c/c++ style pointers, this is safe from the GC (ie not affected by collection) but comes with its own security implications (cant use for internet zone apps) but is excellent for the kind of thing it appears you are trying to achieve especially with performance and even more so with arrays and bitwise operations?

to summarise, you want performance for a small part of your app? use unsafe code and make use of pointers etc seems the best option to me

EDIT: a bit of a starter ? http://msdn.microsoft.com/en-us/library/aa288474(VS.71).aspx

Matt
A: 

Yes you can detect it. If your method is "private static" and small there is a chance compiler can inline it.

In order to detect it uncheck "Just my code" and "Disable JIT optimizations" in Visual Studio (Options -> Debugging). Build your code in "Release" mode and put a breakpoint where you call the function. Then look at JIT disassembly.

ssg
A: 

Is there a way to force the compiler to inline this call or will I do I just hope that the compiler will do this optimization?

If it is cheaper to inline the function, it will. So don't worry about it unless your profiler says that it actually is a problem.

For more information

JIT Enhancements in .NET 3.5 SP1

Jonathan Allen
+1  A: 

Be aware that the XBox works different.

A google turned up this:

"The inline method which mitigates the overhead of a call of a method. JIT forms into an inline what fulfills the following conditions.

  • The IL code size is 16 bytes or less.
  • The branch command is not used (if sentence etc.).
  • The local variable is not used.
  • Exception handling has not been carried out (try, catch, etc.).
  • float is not used as the argument or return value of a method (probably by the Xbox 360, not applied).
  • When two or more arguments are in a method, it uses for the turn declared.

However, a virtual function is not formed into an inline."

http://xnafever.blogspot.com/2008/07/inline-method-by-xna-on-xbox360.html

I have no idea if he is correct. Anyone?

Bengt
Thanks for pointing this out. It's actually quite relevant for me. Would be nice to see it in an official doc though.
Ben S
A: 

The only way to check this is to get or write a profiler, and hook into the JIT events, you must also make sure Inlining is not turned off as it is by default when profiling.

leppie