Inline functions in C#?
Asked Answered
M

13

307

How do you do "inline functions" in C#? I don't think I understand the concept. Are they like anonymous methods? Like lambda functions?

Note: The answers almost entirely deal with the ability to inline functions, i.e. "a manual or compiler optimization that replaces a function call site with the body of the callee." If you are interested in anonymous (a.k.a. lambda) functions, see @jalf's answer or What is this 'Lambda' everyone keeps speaking of?.

Mcqueen answered 23/1, 2009 at 17:31 Comment(2)
It's finally possible - see my answer.Houseroom
For people curious, check out this VS extension.Persons
H
436

Finally in .NET 4.5, the CLR allows one to hint/suggest1 method inlining using MethodImplOptions.AggressiveInlining value. It is also available in the Mono's trunk (committed today).

// The full attribute usage is in mscorlib.dll,
// so should not need to include extra references
using System.Runtime.CompilerServices; 

...

[MethodImpl(MethodImplOptions.AggressiveInlining)]
void MyMethod(...)

1. Previously "force" was used here. I'll try to clarify the term. As in the comments and the documentation, The method should be inlined if possible. Especially considering Mono (which is open), there are some mono-specific technical limitations considering inlining or more general one (like virtual functions). Overall, yes, this is a hint to compiler, but I guess that is what was asked for.

Houseroom answered 5/1, 2012 at 16:38 Comment(8)
It's still probably not a force inline, but overriding the JITters heuristics is certainly enough in most situations.Sibeal
A different approach that can work with all .NET version is to split a slightly too large method into two methods, one that calls the other, neither of which exceeds 32 bytes of IL. The net effect is as if the original were inlined.Gahan
It's not forcing the "Inlining" it's just try to talk with the JIT and tell it that the programmer really wants to use Inlining in here, but the JIT has the final word on it. Hence MSDN: The method should be inlined if possible.Roan
And see https://mcmap.net/q/101503/-how-to-force-inline-functions-in-c-duplicate for an example of how to use it.Quan
By comparison, C++'s inline suggestions, even the compiler-specific ones, also don't actually force an inline: not all functions can be inlined (fundamentally things like recursive functions are hard, but there are other cases too). So yeah, this "not-quite" force is typical.Matsu
I'd say even "if possible" pushes it a bit; there are plenty of cases that the jitter could possibly be extended to deal with, and maybe even will some day, that it won't in-line. Currently it seems to only be a matter of ignoring the size restriction, but since we can expect changes in this regard over the next few years perhaps it is better to just say "makes it more aggressive in deciding whether to inline".Forfeiture
+1, but why dont you simply change "force" to "hint" instead of saying "force" by which I mean "hint". Like in C++ it is a compiler hint.Mika
It's mildly annoying that you cannot almost force the compiler to do it, I am doing a test on codility and the only way for me to get 100% in the speed part is to make a large blob of code, slicing it in function is enough to drop the performance to fail the speed test.Distribution
B
91

Inline methods are simply a compiler optimization where the code of a function is rolled into the caller.

There's no mechanism by which to do this in C#, and they're to be used sparingly in languages where they are supported -- if you don't know why they should be used somewhere, they shouldn't be.

Edit: To clarify, there are two major reasons they need to be used sparingly:

  1. It's easy to make massive binaries by using inline in cases where it's not necessary
  2. The compiler tends to know better than you do when something should, from a performance standpoint, be inlined

It's best to leave things alone and let the compiler do its work, then profile and figure out if inline is the best solution for you. Of course, some things just make sense to be inlined (mathematical operators particularly), but letting the compiler handle it is typically the best practice.

Basanite answered 23/1, 2009 at 17:33 Comment(11)
Normally I think it's OK that the compiler handles inlining. But there are situations where I like to override the compiler decision and inline or not inline a method.Iconoclast
rstevens, I agree, but unless you have a good reason /to/ inline something, I think the best practice is to let the compiler handle it and change it later if profiling shows it's a problem.Basanite
@rstevens: You can always choose to force an inline function by moving the physical implementation of callee to the caller. The reverse, of course, is not so simpleLibra
@Joel Coehoorn: This would be bad practice because it would break modularization and access protection. (Think about an inlined method in a class that accesses private members and is called from different point in the code!)Iconoclast
I need inlining to complicate reverse-engineering. All my protection-related logic uses the same helper functions so it's easy to track all places with protection. Now I'm forced to use copy-paste to prevent this.Karmen
@Karmen That is an odd reason to use inlining. I highly doubt it would prove to be effective.Territus
What about cases where you use inline in order to force lazy evaluation, for which you know it is way faster due to single point modification?Intercede
I have a property that's accessed 3 million times per second, but compiler does not inline it. That's a pretty good case for inling, is there an optimizer possibly to run over generated IL to inline specific calls?Susansusana
The arguments about the compiler knowing best are just wrong. It does not inline any method greater than 32 IL bytes, period. This is horrible for projects (like mine, and also Egor's above) that have profiler-identified hotspots we can do absolutely nothing about. Nothing, that is, except to cut and paste code and so manually inline. This is, in a word, a terrible state of affairs when you're really driving performance.Steading
Inlining is more subtle that it appears. Memory has caches that are fast to access, and the current part of the code is stored in those caches just like variables are. Loading the next cache line of instructions is a cache miss, and costs maybe 10 or more times what a single instruction does. Eventually it has to load into the L2 cache, which is even more expensive. Thus bloated code can cause more cache missed, where an inlined function that stays resident in the same L1 cache lines the whole time could result in fewer cache misses and potentially faster code. With .Net its even more complex.Avebury
@Steading Care to explain what are '32 IL bytes'? Is it the IL source code characters count?Sher
S
64

Update: Per konrad.kruczynski's answer, the following is true for versions of .NET up to and including 4.0.

You can use the MethodImplAttribute class to prevent a method from being inlined...

[MethodImpl(MethodImplOptions.NoInlining)]
void SomeMethod()
{
    // ...
}

...but there is no way to do the opposite and force it to be inlined.

Scut answered 16/1, 2010 at 22:48 Comment(6)
Interesting to know that, but why the heck prevent a method to be inlined? I spent some time staring at the monitor but I can't make up a reason why inlining could do any harm.Hydrophane
If you receive a call stack (i.e. NullReferenceException) and obviously there is no way that the method on top of the stack threw it. Of course, one of its calls may have. But which one?Budgie
GetExecutingAssembly and GetCallingAssembly can give differing results depending on whether the method is inlined. Forcing a method to be non-inlined eliminiates any uncertainty.Devan
@CamiloMartin Several years late, however an example for when Inlining causes harm would be when dynamically loading assemblies. Here is an example.Unkind
"...there is no way to do the opposite and force it to be inlined..." To be clear, there is [MethodImpl(MethodImplOptions.AggressiveInlining)], but whereas NoInlining is conclusively enforced, the latter is merely advisory to the JIT. Also, I'll add another semantic difference besides the one that @Devan already mentioned, as follows...Sinhalese
…Any function that manipulates its in, ref, or out (managed pointer) arguments without pinning is responsible for ensuring the GC-visibility of each. For non-inlined methods, the required stacking—or use of rcx rdx registers, which the GC also knows about—is a bonus byproduct of argument passing. However, this 'free' visibility is not a guarantee of the x64 JIT. When inlined, the managed-pointer arguments of an inline-eligible method may be optimized entirely off the stack, and thus out of GC visibility. The only way to ensure GC correctness is by marking the method NoInlining.Sinhalese
D
38

You're mixing up two separate concepts. Function inlining is a compiler optimization which has no impact on the semantics. A function behaves the same whether it's inlined or not.

On the other hand, lambda functions are purely a semantic concept. There is no requirement on how they should be implemented or executed, as long as they follow the behavior set out in the language spec. They can be inlined if the JIT compiler feels like it, or not if it doesn't.

There is no inline keyword in C#, because it's an optimization that can usually be left to the compiler, especially in JIT'ed languages. The JIT compiler has access to runtime statistics which enables it to decide what to inline much more efficiently than you can when writing the code. A function will be inlined if the compiler decides to, and there's nothing you can do about it either way. :)

Dyspepsia answered 23/1, 2009 at 17:40 Comment(2)
"A function behaves the same whether it's inlined or not." There are some rare cases where this isn't true: namely logging functions that want to know about the stack trace. But I don't want to undermine your base statement too much: it is generally true.Libra
" and there's nothing you can do about it either way. " - not true. Even if we're not counting "strong suggestion" to the compiler as doing anything, you can prevent functions from being inlined.Byrann
L
27

Cody has it right, but I want to provide an example of what an inline function is.

Let's say you have this code:

private void OutputItem(string x)
{
    Console.WriteLine(x);

    //maybe encapsulate additional logic to decide 
    // whether to also write the message to Trace or a log file
}

public IList<string> BuildListAndOutput(IEnumerable<string> x)
{  // let's pretend IEnumerable<T>.ToList() doesn't exist for the moment
    IList<string> result = new List<string>();

    foreach(string y in x)
    {
        result.Add(y);
        OutputItem(y);
    }
    return result;
}

The compilerJust-In-Time optimizer could choose to alter the code to avoid repeatedly placing a call to OutputItem() on the stack, so that it would be as if you had written the code like this instead:

public IList<string> BuildListAndOutput(IEnumerable<string> x)
{
    IList<string> result = new List<string>();

    foreach(string y in x)
    {
        result.Add(y);

        // full OutputItem() implementation is placed here
        Console.WriteLine(y);   
    }

    return result;
}

In this case, we would say the OutputItem() function was inlined. Note that it might do this even if the OutputItem() is called from other places as well.

Edited to show a scenario more-likely to be inlined.

Libra answered 23/1, 2009 at 17:38 Comment(2)
Just to clarify though; it is the JIT that does the inlining; not the C# compiler.Osiris
Also note that, originally at least, the JIT would 'prefer' to inline static methods, even across assembly boundaries. Thus, an old school technique for optimization was to mark your methods as static. This has since been frowned upon by the community but to this day I will still opt to inline methods which are internal, non-polymorphic in nature and typically cost less to execute than the associated stack fill+spill.Dead
A
22

Do you mean inline functions in the C++ sense? In which the contents of a normal function are automatically copied inline into the callsite? The end effect being that no function call actually happens when calling a function.

Example:

inline int Add(int left, int right) { return left + right; }

If so then no, there is no C# equivalent to this.

Or Do you mean functions that are declared within another function? If so then yes, C# supports this via anonymous methods or lambda expressions.

Example:

static void Example() {
  Func<int,int,int> add = (x,y) => x + y;
  var result = add(4,6);  // 10
}
Allergy answered 23/1, 2009 at 17:38 Comment(0)
H
8

Yes Exactly, the only distinction is the fact it returns a value.

Simplification (not using expressions):

List<T>.ForEach Takes an action, it doesn't expect a return result.

So an Action<T> delegate would suffice.. say:

List<T>.ForEach(param => Console.WriteLine(param));

is the same as saying:

List<T>.ForEach(delegate(T param) { Console.WriteLine(param); });

the difference is that the param type and delegate decleration are inferred by usage and the braces aren't required on a simple inline method.

Where as

List<T>.Where Takes a function, expecting a result.

So an Function<T, bool> would be expected:

List<T>.Where(param => param.Value == SomeExpectedComparison);

which is the same as:

List<T>.Where(delegate(T param) { return param.Value == SomeExpectedComparison; });

You can also declare these methods inline and asign them to variables IE:

Action myAction = () => Console.WriteLine("I'm doing something Nifty!");

myAction();

or

Function<object, string> myFunction = theObject => theObject.ToString();

string myString = myFunction(someObject);

I hope this helps.

Hotel answered 23/1, 2009 at 17:38 Comment(0)
R
3

There are occasions where I do wish to force code to be in-lined.

For example if I have a complex routine where there are a large number of decisions made within a highly iterative block and those decisions result in similar but slightly differing actions to be carried out. Consider for example, a complex (non DB driven) sort comparer where the sorting algorythm sorts the elements according to a number of different unrelated criteria such as one might do if they were sorting words according to gramatical as well as semantic criteria for a fast language recognition system. I would tend to write helper functions to handle those actions in order to maintain the readability and modularity of the source code.

I know that those helper functions should be in-lined because that is the way that the code would be written if it never had to be understood by a human. I would certainly want to ensure in this case that there were no function calling overhead.

Roid answered 29/6, 2010 at 20:4 Comment(0)
E
3

The statement "its best to leave these things alone and let the compiler do the work.." (Cody Brocious) is complete rubish. I have been programming high performance game code for 20 years, and I have yet to come across a compiler that is 'smart enough' to know which code should be inlined (functions) or not. It would be useful to have a "inline" statement in c#, truth is that the compiler just doesnt have all the information it needs to determine which function should be always inlined or not without the "inline" hint. Sure if the function is small (accessor) then it might be automatically inlined, but what if it is a few lines of code? Nonesense, the compiler has no way of knowing, you cant just leave that up to the compiler for optimized code (beyond algorithims).

Eldin answered 4/3, 2011 at 22:21 Comment(3)
"Nonesense, the compiler has no way of knowing" The JITer does realtime profiling of function calls..Kinesthesia
The .NET JIT has been known to optimize at run-time better than what is possible with a 2-pass static analysis at compile-time. The hard part for "old school" coders to grasp is that the JIT, not the compiler, is responsible for native code generation. The JIT, not the compiler, is responsible for inline methods.Dead
It's possible for me to compile code that you call into, without my source code, and the JIT may opt to inline the call. Normally I would agree, but I would say as a human you are no longer able to surpass the tools.Dead
S
1

I know this question is about C#. However, you can write inline functions in .NET with F#. see: Use of `inline` in F#

Satinwood answered 22/12, 2012 at 12:45 Comment(1)
I was redirected from here: #13765289Satinwood
I
0

No, there is no such construct in C#, but the .NET JIT compiler could decide to do inline function calls on JIT time. But i actually don't know if it is really doing such optimizations.
(I think it should :-))

Iconoclast answered 23/1, 2009 at 17:43 Comment(0)
S
0

In case your assemblies will be ngen-ed, you might want to take a look at TargetedPatchingOptOut. This will help ngen decide whether to inline methods. MSDN reference

It is still only a declarative hint to optimize though, not an imperative command.

Sothena answered 22/11, 2011 at 19:42 Comment(1)
And the JIT will know much better anyhow whether to inline or not. Obviously won't help you if the JIT doesn't optimize the callsite, but then why the hell should I worry about the minimal overhead of a function that's called only a few times?Diclinous
C
-7

Lambda expressions are inline functions! I think, that C# doesn`t have a extra attribute like inline or something like that!

Cott answered 23/1, 2009 at 17:37 Comment(2)
I did not downvote you, but please read the questions and make sure you understand them before posting a random answer. en.wikipedia.org/wiki/Inline_functionHydrophane
This answer isn't as bad as it has been made out to be - the OP is unclear about 'function inlining' vs 'lambda functions', and unfortunately MSDN refer to lambdas as "inline statements" or "inline code". However, as per Konrad's answer, there is an attribute to hint to the compiler about inlining a method.Descendant

© 2022 - 2024 — McMap. All rights reserved.