Can I have a concise code snippet that would incur JIT inlining please?
Asked Answered
C

2

0

I'm trying to produce some "Hello World" size C# code snippet that would incur JIT inlining. So far I have this:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine( GetAssembly().FullName );
        Console.ReadLine();
    }

    static Assembly GetAssembly()
    {
        return System.Reflection.Assembly.GetCallingAssembly();
    }
}

which I compile as "Release"-"Any CPU" and "Run without debugging" from Visual Studio. It displays the name of my sample program assembly so clearly GetAssembly() is not inlined into Main(), otherwise it would display mscorlib assembly name.

How do I compose some C# code snippet that would incur JIT inlining?

Carmarthenshire answered 2/10, 2012 at 8:26 Comment(4)
I you expect inlining to change the observable behavior of your program, I think you're bound to be disappointed :)Mayce
@jalf: Even when using reflection?Headphone
@jalf: That's not quite correct. Stack traces for example are indeed affected by inlining.Tani
@DanielHilgarth: stack traces do not count as "observable behavior" :)Mayce
Q
6

Sure, here's an example:

using System;

class Test
{
    static void Main()
    {
        CallThrow();
    }

    static void CallThrow()
    {
        Throw();
    }

    static void Throw()
    {
        // Add a condition to try to disuade the JIT
        // compiler from inlining *this* method. Could
        // do this with attributes...
        if (DateTime.Today.Year > 1000)
        {
            throw new Exception();
        }
    }
}

Compile in a release-like mode:

csc /o+ /debug- Test.cs

Run:

c:\Users\Jon\Test>test

Unhandled Exception: System.Exception: Exception of type 'System.Exception' was
thrown.
   at Test.Throw()
   at Test.Main()

Note the stack trace - it looks as if Throw was called directly by Main, because the code for CallThrow was inlined.

Quarters answered 2/10, 2012 at 8:36 Comment(0)
T
1

Your understanding of inlining seems incorrect: If GetAssembly was inlined, it would still show the name of your program.

Inlining means: "Use the body of the function at the place of the function call". Inlining GetAssembly would lead to code equivalent to this:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(System.Reflection.Assembly.GetCallingAssembly()
                                                    .FullName);
        Console.ReadLine();
    }
}
Tani answered 2/10, 2012 at 8:31 Comment(9)
I think his point was that GetAssembly would be invoked by Main, but Main is invoked by something in mscorlib.Headphone
@Rawling: That's not what he is saying in his question: "clearly GetAssembly() is not inlined into Main()"Tani
System.Reflection.Assembly.GetCallingAssembly() returns something different if called directly in main as it does if called in a function that is called by main. Your code produces a different result than the original code. Thus if inlining occurred turning his code into your code, the output would be different.Headphone
@Rawling: That's not correct. You are free to test it yourself.Tani
If I combine your code and the question code - e.g. one WriteLine with System.Reflection.Assembly.GetCallingAssembly(), one with GetAssembly() - I get two different outputs.Headphone
@Rawling: I don't. I get the same output in Release and Debug and if I start it from within VS or directly from disk.Tani
... Oh, that's bizarre. I get Microsoft.VisualStudio.HostingProcess.Utilities ... for the call in Main and MyProject ... for the call in GetAssembly. (Edit: When running from VS. When running standalone, I get MyProject ... for both, so I owe you an apology for that.)Headphone
I assume you start it with debugging (F5)? Try starting without debugging (Ctrl + F5)Tani
Aaaand I've just noticed the comment in the question about going "Run without debugging", which also gives me two identical line. I'm just going to go away now.Headphone

© 2022 - 2024 — McMap. All rights reserved.