Additional optimization in unity for free

What if we already have optimized code and can’t speed up it more, but we want it? There is solution.

What if we already have optimized code and can’t speed up it more, but we want it? There is solution.

Idea

From FW4.6 profile c# supports inlining for methods. Its not forced “must-be-inlined”, but recommendation to compiler, so, we can try it. For this behaviour we should not to do something complex, but just add special attribute and switch C# profile in project settings to FW4.6:

1
2
3
4
5
6
#if NET_4_6
[System.Runtime.CompilerServices.MethodImpl (System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
#endif
public T GetComponent<T> (int entity) where T : class, new () {
var entityData = _entities[entity];
...

#if NET_4_6 preprocessor define should be used for backward compatibility for FW3.5 profile (FW4.6 still experimental). That’s all.

Test code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using System.Collections;
using UnityEngine;
namespace LeopotamGroup.Ecs.Tests {
public class Test8 : MonoBehaviour, IEcsInitSystem {
class C8_1 { }
class C8_2 { }

[EcsWorld]
EcsWorld _world;

IEnumerator Start () {
yield return new WaitForSeconds (2f);
var systems = new EcsSystems (new EcsWorld ()).Add (this);
systems.Initialize ();
systems.Destroy ();
}

void IEcsInitSystem.Initialize () {
const int TESTS = 40;
const int T = 10000000;
var sw = new System.Diagnostics.Stopwatch ();
var result = 0;
C8_1 c1;
C8_2 c2;
var entity = _world.CreateEntity ();
_world.AddComponent<C8_1> (entity);
_world.AddComponent<C8_2> (entity);

for (var test = 0; test < TESTS; test++) {
sw.Reset ();
sw.Start ();
for (var i = 0; i < T; i++) {
c1 = _world.GetComponent<C8_1> (entity);
c2 = _world.GetComponent<C8_2> (entity);
}
sw.Stop ();
result += sw.Elapsed.Milliseconds;
}
Debug.LogFormat ("GetComponent: {0}", result / (float) TESTS);
}

void IEcsInitSystem.Destroy () { }
}
}

Results

Without inline attribute:

1
GetComponent: 188.125

With inline attribute:

1
GetComponent: 134.225

Someting around 30% boost for free. Ecs framework working faster and faster. :)