2

How aggressive in-lining behaves with local functions and abstract methods?

I couldn't find any specific answers to this type of problems.

EDIT: you can't put attribute before local function anymore. - C# 7 Local Functions: are attributes / aspects allowed?

Local function example.

//? Do I have to add [MethodImpl(MethodImplOptions.AggressiveInlining)] before local function for it to be in-lined or is it done by default?

public GameObject Select(LevelProvider provider, int level)
{
    //! This gives an error and I can't apply attribute to local method.
    // So my guess it should always be in-lined. Or does JIT still choose to whether in-line it or not?
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    int GetDistance(GameObject keyGameObject, int levelIndex) => provider.occurrency.TryGetValue(keyGameObject.GetInstanceID(), out int occurencyValue) ? levelIndex - occurencyValue : 0;

    if (!provider.map.TryGetValue(level, out GameObject prefab))
    {
        ...
    }

    return prefab;
}

Abstract example.

public abstract class Base : Object
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public abstract TData Select(TProvider provider);

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public virtual TData Other(TProvider provider)
    {
        ...
    }
}

public class Derived : Base
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)] // !!! Do I have to do this step? !!!
    public override GameObject Select(LevelProvider provider)
    {
        ...
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)] // !!! What about this? !!!
    public override GameObject Other(LevelProvider provider)
    {
        ...
    }
}
  • 1
    It depends on your runtime, it's not a language issue. .NET Framework is not .NET Core which is not Mono, and each of these have different versions with diffferent optimization characteristics. In general, you want to lay off `AggressiveInlining` unless you can show through profiling that the runtime isn't doing a good job, and even if you can, making it do devirtualization (shortcutting virtual calls) usually involves changing code patterns or the way the runtime detects them, not adding explicit attributes, which do not help to suddenly make the devirtualization possible. – Jeroen Mostert Jul 22 '19 at 10:57
  • @JeroenMostert thank you for your comment. I am aware that inlining is decided by compiler. I am not trying to get rid of virtual table or virtual calls. I am trying to understand - do I have to put `AggressiveInlining` every time if I want to ensure that this attribute is applied to a method, or is it inherited with the override of the method. And about local function I couldn't find if it still would need an attribute or if it's always inlined by default by standard .NET compiler, for example. – Candid Moon _Max_ Jul 22 '19 at 11:01
  • @JeroenMostert I have updated my question. Apparently you can't put attribute before local function anymore. Thus question should be just if local functions are always inlined or does the compiler choose when to inline them. – Candid Moon _Max_ Jul 22 '19 at 11:09
  • 1
    Inlining is not decided by the compiler. The compiler translates all methods separately, as methods, as is required by the language semantics, and having names and symbols available in the metadata. It's the jitter (runtime) which ultimately decides if your methods are going to end up inlined, and it's the jitter that decides whether to look at the inheritance chain to respect this attribute or not. (I don't know the behavior of the current jitters; I would not expect any of them to even respect this attribute on virtual methods, because devirtualization is too hard in general.) – Jeroen Mostert Jul 22 '19 at 11:09
  • A local function will end up as a separate, compiler-generated static method, with the prerogative of inlining again left to the jitter. The (draft) language specification currently does not say if this is how the compiler *must* translate it, or if future versions might end up not even emitting them as separate methods if possible. I suspect that the compiler will continue to always emit them as separate methods and leave the rest up to the jitter, just to keep both the implementation and debugging straightforward, and if you really must tweak this you should use an explicit method. – Jeroen Mostert Jul 22 '19 at 11:17

0 Answers0