Can I check if the C# compiler inlined a method call?
Asked Answered
R

10

29

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?

Realism answered 5/3, 2009 at 21:49 Comment(1)
You can (in .Net 4.5). using: [MethodImpl(MethodImplOptions.AggressiveInlining)]Narcotize
W
27

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.

Wie answered 5/3, 2009 at 21:56 Comment(3)
Others beg to differ about reflection since it uses the call stack. #44653Realism
I didn't say reflection, I said reflector, as in Red Gates .NET Reflector.Wie
My bad, I misunderstood that.Realism
R
19

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

--Joel Coehoorn

Realism answered 5/3, 2009 at 21:56 Comment(3)
Of course it will only work at runtime, that is when inlining occurs.Crissie
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?Grannie
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.Medusa
J
15

There is a new way to encourage more agressive inlining in .net 4.5 that is described here: http://blogs.microsoft.co.il/blogs/sasha/archive/2012/01/20/aggressive-inlining-in-the-clr-4-5-jit.aspx

Basically it is just a flag to tell the compiler to inline if possible. Unfortunatly, it's not available in the current version of XNA (Game Studio 4.0) but should be available when XNA catches up to VS 2012 this year some time. It is already available if you are somehow running on Mono.

[MethodImpl(MethodImplOptions.AggressiveInlining)] 
public static int LargeMethod(int i, int j)
{ 
    if (i + 14 > j) 
    { 
        return i + j; 
    } 
    else if (j * 12 < i) 
    { 
        return 42 + i - j * 7; 
    } 
    else 
    { 
        return i % 14 - j; 
    } 
}
Jdavie answered 20/3, 2012 at 17:48 Comment(0)
S
4

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?

Strath answered 6/3, 2009 at 11:57 Comment(1)
Thanks for pointing this out. It's actually quite relevant for me. Would be nice to see it in an official doc though.Realism
S
1

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.

Squadron answered 5/3, 2009 at 21:51 Comment(17)
"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?"Realism
Nope, I doubt the C# compiler does any inlining at all. JIT compiler is responsible for that.Squadron
You can check System.Reflection.MethodBase.GetCurrentMethod().Name. If the method is inlined, it will return the name of the caller instead.Jeunesse
And the compiler does occasionally inline a method.Jeunesse
Joel - you should submit that as an answer to the second part of his question.Preach
Jeol: are you sure about that?Squadron
Meh: thought about it, but I wouldn't have had a clue without reading this answer first. I have enough rep.Jeunesse
I posted it and attributed you, future readers won't have to look at comments to find the answer.Realism
@Mehrdad: Pretty sure. Learned about it here first, and several of the answers there brought up inlining as something to watch for: stackoverflow.com/questions/44153Jeunesse
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.Squadron
Good point about the optimizer being the culprit, but it still happens :)Jeunesse
@Meh: I believe inlining will only occur on non-virtual calls.Gilbertine
@Mark: by overriding I didn't mean virtual calls. I meant reprogramming a method dynamically by means of reflection.Squadron
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. :)Squadron
@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.Gilbertine
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 :)Squadron
@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.Gilbertine
R
1

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

Raynard answered 5/3, 2009 at 23:1 Comment(1)
unsafe code is often slower than managed code, because the JIT cannot make as many guarantees about your code so it can't do certain optimizations. So if you do this, as always, profile!Pell
D
1

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.

Doehne answered 6/3, 2009 at 12:4 Comment(0)
G
0

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.

Gilbertine answered 5/3, 2009 at 22:3 Comment(1)
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.Jeunesse
C
0

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

Crissie answered 6/3, 2009 at 0:7 Comment(0)
L
0
Larceny answered 2/3, 2019 at 23:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.