Бесплатная дополнительная оптимизация кода в Unity
Размещено
Что если мы уже оптимизировали код, но хотим его ускорить еще немного? Есть решение.
Идея
Начиная с FW4.6 C# поддерживает рекомендации по инлайнингу для компилятора. Результат не обязательно будет заинлайнен, это именно рекомендация, но в общем случае оно прекрасно работает. Для активации мы должны добавить специальный атрибут к каждому методу, который хотим заинлайнить, а так же убедиться, что используем 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 позволяет использовать данный код и на FW3.5-профиле, т.е обеспечивает обратную совместимость (разумеется, с потерей инлайнинга).
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 () { } } }
Результаты
Без инлайнинга:
1
GetComponent: 188.125
С инлайнингом:
1
GetComponent: 134.225
Примерно 30% ускорения, причем бесплатно. ECS фреймворк работает все быстрее и быстрее. :)