Search Unity

ОПТИМИЗАЦИЯ СЕРВЕРНОЙ ЧАСТИ ПОЛЬЗОВАТЕЛЬСКОГО ИНТЕРФЕЙСА

, Сентябрь 7, 2015

В Unity 4.6 / 5.0 существует проблема: пакеты данных для рендеринга пользовательского интерфейса генерируются очень медленно. Этому есть несколько причин, но главным образом это произошло из-за нехватки времени на оптимизацию этой части интерфейса. Тогда мы были слишком заняты работой над программным интерфейсом и доступностью пользовательского интерфейса, а срок поджимал. Закончив работу над этими версиями, мы решили провести анализ, чтобы узнать, как лучше исправить ситуацию.

В итоге к версии 5.2 мы убрали обработку интерфейса (кроме планировки задач) из основного потока, а также внесли исправления в некоторые алгоритмы, используемые для сортировки пакетов.

Наша цель производительность

Мы разработали несколько тестовых сцен для испытания производительности интерфейса, чтобы получить исходную точку для работы над оптимизацией. Эти сцены подвергают интерфейс сильной нагрузке различными способами. К примеру, одна из них полностью заполняет экран кнопками, что хорошо подходит для проверки оптимизации сортировки и генерации пакетов. Во время тестирования элементы интерфейса постоянно изменяются, и с каждым кадром производится перерасчет. Используется около 10 тыс. элементов интерфейса (в реальном интерфейсе на рабочем поле бывает около 300 элементов).

Тест может размещать элементы интерфейса упорядоченно или в случайном порядке, и во втором случае алгоритм сортировки использует больше вычислительных ресурсов. Необходимо, чтобы сортировка пакетов проходила быстро, но в версиях 4.6 и 5.0 она серьезно замедляется в обоих вариантах сцены.

Для тестов использовался MacBook Air 13, модель 2013 г.

Часть сцены:unnamed

Версии до 4.6

Получив отчеты по бета-тестированию 4.6, мы узнали о том, что сортировка пакетов сильно замедляется при наличии большого количества элементов на рабочем поле. Оказалось, что алгоритм сортировки недостаточно совершенен. После итерации проводилась проверка на столкновения и присвоение глубины по установленным правилам, и с добавлением большого количество элементов скорость алгоритма сильно снижалась (O(N^2)).

Версии 4.6 / 5.0

Мы разработали новый алгоритм. Основной принцип: упорядоченные элементы обычно отображаются в том же порядке. Производится построение прямоугольной границы для группы из N элементов, и новые элементы сначала проверяются на столкновение с этой группой, а потом — с отдельными элементами. При этом достигается достаточное быстродействие в тех случаях, когда элементы интерфейса находятся рядом. Однако в тех случаях, когда их расположение случайно или же они расположены далеко друг от друга, улучшение практически незаметно. В одном из примеров при добавлении случайных элементов скорость серьезно упала, и создание сцены заняло 100 мс, что никуда не годится.

unnamed (1)

Кроме того, из временного профиля на изображении становится ясно, что этот алгоритм не позволяет производить дополнительных действий. Генерация пакетов происходит прямо перед рендерингом интерфейса, часто после вызова LateUpdate и рендеринга камер сцены. Следовало бы перенести генерацию назад, чтобы она происходила сразу после LateUpdate, одновременно с рендерингом сцены.

unnamed (2)

Оптимизация сортировки (часть 1)

Первая попытка оптимизации алгоритма сортировки всё ещё основывалась на идее локальности элементов, но с некоторыми улучшениями. Был сделан акцент на оптимальность групп элементов с точки зрения процесса генерации пакетов. Было достигнуто некоторое ускорение, однако при обработке сцен с большими пространствами между элементами все равно происходило замедление. Кроме того, алгоритм плохо масштабировался на большое количество элементов.

Элементы не сгруппированы в пространствеunnamed (3)

Элементы сгруппированы в пространстве
unnamed (4)

После этого мы решили, что необходим новый подход.

Оптимизация сортировки (часть 2)

Нам требовался такой алгоритм сортировки, который не замедлял бы обработку больших сцен с разнесенными элементами. В конце концов мы добавили сетку рабочего поля. К каждой ячейке сетки привязана группа, к которой приписываются элементы, прикасающиеся к ячейке, поэтому при добавлении нового элемента нужно рассматривать только те группы, к ячейкам которых прикасается элемент, чтобы узнать, с какими другими элементами он может быть объединен в пакет. После этого скорость обработки сцен, особенно в случаях со случайными сценами, серьезно возросла.

Элементы не сгруппированы в пространстве unnamed (5)

Элементы сгруппированы в пространствеunnamed (6)

Geometry Job

Компонент GeometryJob — одно из нововведений, добавленных в Unity 5. Мы воспользовались им, чтобы отделить обработку интерфейса от основного потока. GeometryJob используется для заполнения вершинных (индексных) буферов. Его возможности позволили снять большое количество кода с основного потока. Задание и инструкции к нему занимают некоторые количество памяти, однако оно незначительно по сравнению с высвобожденными ресурсами.

unnamed (7)

Упрощение сортировки пакетов

Мы также выполнили серию оптимизаций меньшего масштаба. Наиболее значимой из них была векторизация проверок на пересечение прямоугольников во время сортировки. Ранее эти проверки занимали до 60% времени сортировки.

После векторизации проверок
unnamed (8)

Taking it all off (the main thread)

Следующий логический шаг — полностью убрать генерацию интерфейса из основного потока. Мы использовали внутреннюю систему для составления списка задач для параллельного и последовательного исполнения:

1) Разделение входящих инструкций к интерфейсу на множество инструкций, пригодных для рендеринга (в одной инструкции к интерфейсу может быть много запросов на отрисовку из-за использования различных материалов и подсеток). Память выделяется на максимально возможное количество полученных инструкций, которые обрабатываются параллельно и помещаются в выходной массив, который сжимается в единую секцию памяти, содержащую только допустимые инструкции.

2) Сортировка инструкций. Сравниваются глубины, перекрытия и т.д. В результате получается буфер команд, который будет требовать наименьшее возможное изменение состояния системы во время рендеринга.

3) Генерация пакетов

  1. Генерация буфера команд для рендеринга, создание вызовов к рисовке.
  2. Генерация инструкций на трансформацию, используемых Geometry Job.

Задания планируются после LateUpdate. Они выполняются во время рендеринга сцены и до появления интерфейса на экране. Когда эти задания планируются, на основном потоке ставится барьер: вызовы на рендеринг рабочего поля и GeometryJob ждут генерации нужных данных.

В примере видно, как задание GeometryJob останавливается и ждет генерации пакетов. В этих сценах элементы интерфейса — единственное, для чего нужен рендеринг; мы считаем, что проблема остановки менее серьезна в тех случаях, когда обрабатываются сложные сцены.

unnamed (9)

Выполнение на компьютере с большим количеством ядер, чем мой  MacBook Air
unnamed (10)
Итог: 0,4 мс для основного потока при использовании сложного интерфейса.

Различные улучшения производительности

  • Граница отсечения (оказалось, что в большинстве интерфейсов не нужен буфер шаблонов; сделана для уменьшения количества вызовов к рисовке и изменений состояния).
  • Граница отбрасывания (отбрасываются все элементы вне границы рендера).
  • Умный буфер команд рабочего поля.
    • Общие шейдеры и материалы для нормальных элементов и текстов.
    • Уменьшение количества вызовов Set Pass.
    • Большое количество специфических данных интерфейса убрано в блоки свойств материалов.
    • Сначала один вызов Set Pass, затем множество вызовов рисовки.
  • * Единый буфер индексов для интерфейса.
    • Для рендеринга используется DrawIndexRange.
    • Единый буфер VBO / индексов, масштабируется по ситуации.
    • Используется следующий вызов рисовки, когда индексов более 2^16.

Дальнейшие шаги

Скорость генерации и сортировки пакетов стала удовлетворительной. Конечно, их оптимизацию можно продолжать и далее, но больше всего времени сейчас занимает GeometryJob, изолированная от основного потока. Скорее всего, в других аспектах также есть неоптимальные решения; например, можно векторизовать медленные вычисления. Все реализованные улучшения уже включены в Unity 5.2.

Заключение

Благодаря нововведениям Unity 5.2 им мы смогли минимизировать нагрузки интерфейса на основной поток и оптимизировать сбор пакетов. Во процессе работы мы использовали Unity Profiler для поиска проблемных участков. Несколько раз нам приходилось начинать заново, так как предыдущее решение оказывалось неоптимальным. В этом заключается значительная часть работы над Unity: поиск и решение проблем, о которых нам сообщаете вы. Вместе с вами мы делаем Unity лучше.

Команда UI

Комментарии закрыты.

  1. The UI is still broken in the latest 5.2.0p1. Half of the gui is unclickable. raycasts go thru.
    Maybe thats why the gui is faster, because IT IS NOT WORKING.

    1. What I want to know is if these improvements can be applied to the Legacy GUI system.
      The UGUI system is kinda unwieldly, and it’s difficult to make procedural layouts that use data, which is something the Legacy GUI is incredibly good at doing.

      After a little bit of fiddling with both, I’d even say the Legacy GUI is easier to make look good at different resolutions than UGUI is, and it doesn’t clutter up the hierarchy with tons of objects.

    2. If there is an eventsystem in the scene (and no graphic raycasters), then your UI will not be clickable.

      For every canvas root node you should ensure you have a Graphic Raycaster, as a graphicRaycaster does not raycast nest UI elements on canvas root nodes not in the same root node as tha Raycaster itself.

      You also need some kind of InputModule in the scene, either one of the default InputModules, or one created by yourself.

      I have no problems making the UGUI system work for me, using my own InputManager/Inut module handlers.

  2. I also upgraded to 5.2 and for my iOS game the CPU usage dropped from 45% to 20%. Great! But on the other hand the GPU usage increased, which now makes my game a lot slower. In the xcode performance profiler the renderer now runs constantly at 100%, before it only ran at 33%.

    Very strange…:(

  3. I upgraded to 5.2 yesterday and it’s killing me softly. So many weird issues now. My Android game is pretty much unplayable at this point. Reverting to 5.1.3.

  4. i see, tried the 5.2.0 and i think its faster because it is not working. complete canvases cant get raycasts.
    buttons not working.
    as you can see from here others also noticed it: http://forum.unity3d.com/threads/upgrading-to-unity-5-2-ui-problem-with-raycast-target.353586/
    the whole game is now broken. had to fall back to 5.1.3p2 and now everything works again.

  5. I don’t see shadows or other mesh modifiers in Performance Project (looking in picture), they heavily influence on UI performance / memory allocations and are the bottleneck of whole system.

  6. Interesting!I will update unity 5.2~

  7. This rules! Thanks for going so in depth. We are updating our UI heavy project, XPETS, to 5.2 right now. Excited to see if we get some performance increases!

  8. First tests shows a dramatic decrease in frame rate for our UI-based game.

    For one Android phone the frame rate dropped to about half of Unity 5.1.2. Will analyse why this is happening in the coming week. We had performance problems before and they are far worse now…

  9. Whether is the 2D Rect Mask only for rectangle mask, not for nonRectangle mask?

    1. အမ ရ ထ တ လ တ ဖတ ပ ည လ မ အ မ ပ ပသ ရတယ ..ဒ လ ပ ပ ..လ တစ ယ က မ တစ ခ ခ က တ ထ ခ ကတ ခ ည ပ ပ …အမမ လ ထ ခ တ attraction တရပ ရ နတယ ..အ ဒ က ဘ လ တ ပ တတ ဘ …အမစ က ဖတ ပ ရင သ တယ လ တ တ မ တယ ….အမ ပ ရ င ပ စ… န က ဆ ပ တ စ သ လ အ တ က က မ သဗ ..ဘ တ .. ရ င ရယ က ရ င ရယ ……… ခင တ …မ နတ

  10. Great job, one more reason to complete my transition to the new UI.

    Quick question: should we expect benefits from multithreading when making 3D UIs ? Are they also rendered at the end of the frame ? (I would assume they are not)
    What about rendering the UI to a rendertexture? I suspect multithreading would not provide the same gain for similar reasons

  11. Hi,

    Great news, I just have one small question. What exactly do you mean with «vectorised a bunch of our rectangular overlap checks in the sorting» and «and it’s also using a bunch of slow maths that could handle being vectorised very nicely»? Could you give one small example?

    1. Allows us to perform the same operation on datasets in a parallel way. https://en.wikipedia.org/wiki/SIMD

  12. Do you rewrite the whole UI System and Change the API of UI System? And Is it expensive to update existing project to unity 5.2? finally, Whether is the new UI System compatible with the old UI System’s API?

    1. This was for the in game 4.6+ UI system. API is the same, just a backend upgrade.

  13. Since you mention command buffers, will we have the ability to use the UI system with the existing command buffer API? Specifically, I want to render canvas renderers to a render texture, but I think it only works with mesh renderers. Maybe also expose the UI rendering step in the CameraEvent. This would be quite useful for making special effects for the UI, especially for text.

  14. Yeah, just when I need it.

  15. That parallel UI/geometry rendering scheme is a thing of beauty! Great job guys!

    We are currently in the process of updating ALL of KSP’s UI to use 4.6/5 canvas components (from the many redundant/conflicting UI solutions we had before)… That in itself is already a massive load off our frame times, so Unity 5.2 should make our UI overhaul that much more worth the effort!

    Very great news indeed! Many thanks from the KSP team!

    Cheers

    1. Looking forward to seeing what you come up with :)

  16. Is there any hope of UI performance improvements in 4.6.x? (The move to 5 is not a trivial thing for projects with a lot of baked lighting…)

    1. 6 comments below, Tim wrote «Only for 5.2».

  17. Good Job UI Team!

    You don’t know how many games are just UI-based ;)

    Cheers

  18. Is Unity 5.2 still slated for tomorrow?

    1. Yes

  19. Hey, I’d love a blog post talking about what you are planning to visual scripting :D

    1. Just cause it’s simple doesn’t mean it’s not super helpufl.

    2. Heck yeah ba-ebye keep them coming!

  20. Is this UI optimisation benefit the 2d sprite sorting for isometric map ?

    1. *You* are awesome! And I might re-think cnninag at some point now that you’ve brought to mind the possibility of doing it in December rather than the summer! I loved cnninag days as a child, but it was alway so hot.

  21. Also take a look at UI performance when used with Unity’s animation system, for me, completely killing performance.

    1. I’m experiencing the same problem when attempting to fade in/out a group of UI elements.

  22. Only for Unity 5.2? Not 4.x?

    1. Only for 5.2

  23. «We reached the first step on the path to pulling the UI off the main thread by using the new Geometry Job system which was introduced in Unity 5. This is an internal feature that can be used to populate a vertex / index buffers in a threaded way.»

    In this sentence, the word «internal» really sucks :D.

    Any idea when mere mortals.. I mean when «us users» can implement and shedule jobs like this? ;)

    1. I can’t say currently. I’m not sure if it’s on the roadmap.

      1. Ability to efficiently «create» geometry from threads (i.e. exposing our «geometry job» thing to scripting) is on the wish list of things we want to do. We have some experiments in that area, but nothing we’re ready to ship/test yet. Stay tuned!

        1. we cannot wait to give this a go as the current dynamic mesh generation is the main cpu bottleneck for us

      2. Weeeeh! Same here, Bless, ang Triz maoy paspas kaayo mataikka sa iyahang name. Sa nag-tour mi sa school, ang amahan nawala pa, ang Triz diritso nakahinumdom sa locker nila. Ah kids!As for the bus riding, it’s Triz’s 3rd day today and for the past 2 days, she had enjoyed the experience. We asked her if she wants to be dropped by pero niingon man nga she is fine with riding the bus. I was all worried at first, pero pagkakita naku nga daghan pa mas gamay sa iyaha, katong mga kinder pa, na-comforted ra ko. Shiloh will do great for sure! And the mommy? Nah worries will always be there! Early BPC hopping here!

  24. Now this is finally great news, especially for slow but heavily multicore oriented platforms like Android or iOS in the future (the ipad air2 sits on 3 cores) :D

    Congratulations, looking forward to run further tests on 5.2 more sooner than later.

  25. Great to see this sort of a hard focus on optimization, this actually might be the last kick I need to migrate over to the new UI & update to 5.2 once it’s out!