Мерять будем как и в оригинальной статье - через Graphy, ведь профессионалы меряют все кадрами в секунду, а не миллисекундами, не будем от них отставать! Заодно и потребление памяти померяем, чтобы мне стало стыдно за жирные SparseSet-ы и зря потраченную память в LeoECS Lite и LeoECS Proto.
Замеры сделаны в сборках под MacOS, собранных с помощью IL2CPP (Release) и запущенных на следующем железе:
Тесты
Тесты как и в оригинальной статье будут состоять из 3 частей:
Простое итерирование с обновлением полей компонентов
Итерирование с миграцией сущностей при удалении/добавлении 1 компонента
Итерирование с миграцией сущностей при удалении/добавлении 3 компонентов.
Во всех тестах используется одно количество сущностей : 500_000.
Итерирование
Все системы помечены IL2CPP-атрибутами (убраны из примеров кода для краткости):
classTestAspect : ProtoAspectInject { public ProtoPool<TestComponent0> Pool0; public ProtoPool<TestComponent1> Pool1; public ProtoPool<TestComponent2> Pool2; public ProtoPool<TestComponent3> Pool3;
public ProtoIt It0 = new (It.Inc<TestComponent0> ()); public ProtoIt It1 = new (It.Inc<TestComponent0, TestComponent1> ()); public ProtoIt It2 = new (It.Inc<TestComponent0, TestComponent1, TestComponent2> ()); public ProtoIt It3 = new (It.Inc<TestComponent0, TestComponent1, TestComponent2, TestComponent3> ()); }
publicvoidInit (IProtoSystems systems) { for (var i = 0; i < Consts.ENTITIES_COUNT; i++) { var e = _aspect.World ().NewEntity (); _aspect.Pool0.Add (e); _aspect.Pool1.Add (e); _aspect.Pool2.Add (e); _aspect.Pool3.Add (e); } }
publicvoidRun () { foreach (var ent in _aspect.It3) { _aspect.Pool0.Get (ent).Test++; _aspect.Pool1.Get (ent).Test++; _aspect.Pool2.Get (ent).Test++; _aspect.Pool3.Get (ent).Test++; } } }
Результаты
LeoECS Lite 2023.11.22 (release)
Morpeh 2023.1.0 (release)
Morpeh 2024.1.0-rc46 (dev)
DragonECS: 0.8.31 (dev)
LeoECS Proto 2024.4.25 (boosty release)
LeoECS Proto 2024.4.25 (boosty release)
Итерации с кеширующими итераторами (при этом зависимые компоненты не могут удаляться или добавляются)
Выводы
Видна значительная деградация релизной версии Morpeh 2023.1.0 по сравнению с 2022 годом (тогда скорость была примерно одинакова с LeoECS Lite), в Morpeh 2024.1.0-rc46 скорость более-менее возвращена к той, что была ранее. Налицо отсутствие системного подхода к контролю качества, иначе это было бы исправлено сразу, а не через год.
Потребление оперативной памяти: Morpeh 2023.1.0 потребляет 300Мб - это в 6.5 раз больше, чем потребляет LeoECS Lite и в 10 раз больше, чем LeoECS Proto! И это по сути только инфраструктурные издержки, самих данных компонентов там практически нет. В Morpeh 2024.1.0-rc46 потребление памяти снизили в 2 раза, но на общем фоне это мало что поменяло - 160Мб это очень много по сравнению с потенциальными 30Мб. А потом эти люди учат меня, что SparseSet-ы размером с мир много занимают и так делать нельзя, а Morpeh является “production-ready” и там все сделано правильно.
Новичок DragonECS показал себя неплохо, он еще не в релизе и есть куда развиваться.
Миграции одного компонента
Код инициализации систем идентичный коду из предыдущего теста, будет приведена только отличающаяся часть кода.
LeoECS Lite
1 2 3 4 5 6 7 8 9
publicvoidRun (IEcsSystems systems) { foreach (var ent in _filter3) { _pool3.Del (ent); }
foreach (var ent in _filter0) { _pool3.Add (ent); } }
Morpeh
1 2 3 4 5 6 7 8 9
publicoverridevoidOnUpdate (float deltaTime) { foreach (var ent in _filter3) { _stash3.Remove (ent); } World.Commit (); foreach (var ent in _filter0) { _stash3.Add (ent); } }
DragonECS
1 2 3 4 5 6 7 8 9
publicvoidRun () { foreach (var ent in _world.Where (out Aspect3 a3)) { a3.C3.Del (ent); }
foreach (var ent in _world.Where (out Aspect0 a0)) { a0.C3.Add (ent); } }
LeoECS Proto
1 2 3 4 5 6 7 8 9
publicvoidRun () { foreach (var ent in _aspect.It3) { _aspect.Pool3.Del (ent); }
foreach (var ent in _aspect.It0) { _aspect.Pool3.Add (ent); } }
Результаты
LeoECS Lite 2023.11.22 (release)
Morpeh 2023.1.0 (release)
Morpeh 2024.1.0-rc46 (dev)
DragonECS: 0.8.31 (dev)
LeoECS Proto 2024.4.25 (boosty release)
Выводы
LeoECS Lite ожидаемо просаживается по скорости из-за необходимости постоянно обновлять несколько фильтров. Странно, что Morpeh 2024.1.0-rc46 не показывает фантастических результатов, как обещали разработчики.
LeoECS Proto ожидаемо игнорирует количество обновляемых фильтров, просаживаясь только на самом добавлении/удалении компонентов.
Новичок DragonECS прекрасно показал себя на миграции, выдав результат в 2 раза лучше, чем Morpeh 2024.1.0-rc46! Когда один разработчик лучше, чем целая команда.
Миграции трех компонентов
LeoECS Lite
1 2 3 4 5 6 7 8 9 10 11 12 13
publicvoidRun (IEcsSystems systems) { foreach (var ent in _filter3) { _pool1.Del (ent); _pool2.Del (ent); _pool3.Del (ent); }
foreach (var ent in _filter0) { _pool1.Add (ent); _pool2.Add (ent); _pool3.Add (ent); } }
Morpeh
1 2 3 4 5 6 7 8 9 10 11 12 13
publicoverridevoidOnUpdate (float deltaTime) { foreach (var ent in _filter3) { _stash1.Remove (ent); _stash2.Remove (ent); _stash3.Remove (ent); } World.Commit (); foreach (var ent in _filter0) { _stash1.Add (ent); _stash2.Add (ent); _stash3.Add (ent); } }
DragonECS
1 2 3 4 5 6 7 8 9 10 11 12 13
publicvoidRun () { foreach (var ent in _world.Where (out Aspect3 a3)) { a3.C1.Del (ent); a3.C2.Del (ent); a3.C3.Del (ent); }
foreach (var ent in _world.Where (out Aspect0 a0)) { a0.C1.Add (ent); a0.C2.Add (ent); a0.C3.Add (ent); } }
LeoECS Proto
1 2 3 4 5 6 7 8 9 10 11 12 13
publicvoidRun () { foreach (var ent in _aspect.It3) { _aspect.Pool1.Del (ent); _aspect.Pool2.Del (ent); _aspect.Pool3.Del (ent); }
foreach (var ent in _aspect.It0) { _aspect.Pool1.Add (ent); _aspect.Pool2.Add (ent); _aspect.Pool3.Add (ent); } }
Результаты
LeoECS Lite 2023.11.22 (release)
Morpeh 2023.1.0 (release)
Morpeh 2024.1.0-rc46 (dev)
DragonECS: 0.8.31 (dev)
LeoECS Proto 2024.4.25 (boosty release)
Выводы
LeoECS Lite практически мертвый на таком количестве сущностей при постоянном обновлении всех фильтров.
Morpeh 2024.1.0-rc46 быстрее, чем Morpeh 2023.1.0, но незначительно.
Новичок DragonECS показывает скорость в 2 раза большую (при потреблении памяти в 2 раза меньше), чем у “лучшего, самого быстрого, production-ready” Morpeh-а и в этот раз. Рекомендую сходить и поставить звезду этому репозиторию, автор DragonECS это заслужил!
LeoECS Lite с 22.05.2024 переводится из активной разработки в режим поддержки - будут исправляться только баги, нового функционала не планируется. На текущий момент известных багов нет, фреймворк стабильный и выполняет свои задачи.
Актуальные версии пакетов доступны в закрытом discord-сервере для vk/boosty-подписчиков.