Entitas icon indicating copy to clipboard operation
Entitas copied to clipboard

Generated code is suboptimal on IL2CPP target

Open dkozlovtsev opened this issue 5 years ago • 2 comments

Hi,

After updating to latest version we've noticed a considerable slowdown in Adding/Replacing components, after some investigation it turned out that Jenny started to generate code that contains typeof() which isn't really fast (in no AOT environment it is at least JIT'ed away, in IL2CPP it is slow every time it is called) before update generated code looked like this:

public partial class GameEntity {

    public Level level { get { return (Level)GetComponent(GameComponentsLookup.Level); } }
    public bool hasLevel { get { return HasComponent(GameComponentsLookup.Level); } }

    public void AddLevel(string newName) {
        var index = GameComponentsLookup.Level;
        var component = CreateComponent<Level>(index);
        component.name = newName;
        AddComponent(index, component);
    }

    public void ReplaceLevel(string newName) {
        var index = GameComponentsLookup.Level;
        var component = CreateComponent<Level>(index);
        component.name = newName;
        ReplaceComponent(index, component);
    }

    public void RemoveLevel() {
        RemoveComponent(GameComponentsLookup.Level);
    }
}

and after it became:

public partial class GameEntity {

    public Level level { get { return (Level)GetComponent(GameComponentsLookup.Level); } }
    public bool hasLevel { get { return HasComponent(GameComponentsLookup.Level); } }

    public void AddLevel(string newName) {
        var index = GameComponentsLookup.Level;
        var component = (Level)CreateComponent(index, typeof(Level));
        component.name = newName;
        AddComponent(index, component);
    }

    public void ReplaceLevel(string newName) {
        var index = GameComponentsLookup.Level;
        var component = (Level)CreateComponent(index, typeof(Level));
        component.name = newName;
        ReplaceComponent(index, component);
    }

    public void RemoveLevel() {
        RemoveComponent(GameComponentsLookup.Level);
    }
}

The latter isn't fast image (Type_GetTypeFromHandle is what typeof becomes) All those GetTypeFromHandle amounted to 6% of all cpu time for my app and it is quite a lot.

This change is related to #780, but it does no quite the same thing as reporter suggested. I tried both reverting to old generated code and to follow the #780 author suggestion and in both cases the performance improved significantly.

dkozlovtsev avatar Jun 14 '19 07:06 dkozlovtsev

Just thinking. Slowness of generic CreateComponent<T> might come from usage of Activator.CreateInstance<T>(); it can safely be changed to new T(). Manual inlining without Activator as suggested in improvement looks good too

c0ffeeartc avatar Jun 14 '19 09:06 c0ffeeartc

Just thinking. Slowness of generic CreateComponent<T> might come from usage of Activator.CreateInstance<T>(); it can safely be changed to new T().

Actually, new T() in generic method turns into Activator.CreateInstance<T>() after compilation

dkozlovtsev avatar Jun 18 '19 13:06 dkozlovtsev