Комментарии 67
Связано это, якобы, с другой реализацией сбора мусора и туманным Editor OverheadПопробуйте запустить не в редакторе, а собранное приложение.
Раз уж запускали в редакторе — что говорит профайлер? Куда уходит основное время? На каких версиях производили сравнение?
Реализация: github.com/hippogamesunity/SimpleGif/blob/master/SimpleGif/GifCore/LzwEncoder.cs
В консольном приложении на тестовом массиве эта операция выполняется за 18 ms. В Unity она же выполняется за 380 ms.
Скриншот профайлера по этой операции: yadi.sk/i/dMwQV18X3YgDhy
Выходит, что базовая операция вроде проверки ключа в словаре выполняется в Unity в 20 раз медленнее.
Похожая проблема: answers.unity.com/questions/325710/dll-call-10x-slower-in-unity.html
Дальше не смотрел, но этого достаточно чтобы сильно засомневаться в адекватности как минимум бенчмарка.
Почитайте зачем нужен как минимум volatile.
Переменную необходимо объявлять как volatile в тех случаях, когда ее значение может быть изменено чем-либо, не зависящем от того участка кода, в котором она фигурирует (например, параллельно выполняющимся потоком).То есть данные посчитаны, но в потоке еще не появились и этот цикл молотит впустую пока не сбросится кеш.
retran, вы это хотели сказать?
2. Вы измеряете время выполнения кода с Thread.sleep внутри. Который в принципе может вести себя непредсказуемо.
Посмотрел реализации EncodeParallel/DecodeParallel:
1. Параллельный код так в целом писать не стоит, но придираться не буду.
2. Такая реализация дает очень высокий contention, то есть ваши потоки скорее всего большую часть времени висят на блокировках.
Я бы:
1. Переписал бы код без блокировок, для этого алгоритма это легко.
2. Посмотрел бы как устроен ThreadPool в Unity. И погонял бы под профайлером. Я ничего не знаю о Unity, но почти уверен, что дело в разнице реализаций.
UPD Я не уверен, что это даже тот же самый пул, но мало ли :)
1. строковый ключ в алгоритме сжатия LZW, заменил
next = code + " " + colorIndexes[i];
на
next = 257 * (code + 1) + colorIndexes[i];
2. использование LINQ для больших коллекций. Похоже действительно, у сборщика мусора появляется много работы после реализации LINQ в Unity. Убрал LINQ где это было уместно.
Проблем с потоками в Unity нет, все работает как и в консольном приложении.
Почему потоки висят в блокировках, если в lock расположены только присвоения, там нет никаких вычислений?
Кроме того, это не дает ответа на вопрос, почему этот же код в Unity работает в 20 раз медленнее)
Как я понимаю в Unity вообще своя система работы с многопоточностью. И если Вам надо написать производительное приложение консольное, то вы можете использовать System.Threading.
Программа на C# запускается как единственный поток, автоматически создаваемый CLR и операционной системой (“главный” или первичный поток), и становится многопоточной при помощи создания дополнительных потоков.
В Unity же дела обстоят совсем иначе. Там исконно все объекты являются производными от MonoBehaviour, что создает разного рода накладки. Не шибко производительным код считается из-за плохой организации хранения объектов в памяти и доступа к ним. Так же многие встроенные методы (Start, Update, Awake) работают по принципу черного ящика и где именно находится точка входа сложно понять как и понять в каком порядке они вызываются. По хорошему посмотреть Ваш проект на Unity, посмотреть на то как там вызываются все методы, как Вы адоптировали код. Если вы импортировали библиотеки, то имеет место overhead вызова метода и загрузки библиотеки, а если вы в каждом кадре такое делаете, то не мудрено что производительность упала многократно. Так же возникают и свои накладки в работе Garbage Collector'а, если у вас создается слишком много объектов, которые потом редко используются.
Писать приложение в консоли и писать в Unity это 2 разные вещи. В помощь могу Вам посоветовать вот эту статью, которая, возможно, поможет ответить на Ваши вопросы.
https://software.intel.com/en-us/articles/putting-your-data-and-code-in-order-data-and-layout-part-2
C# Job System
software.intel.com/en-us/articles/get-started-with-the-unity-entity-component-system-ecs-c-sharp-job-system-and-burst-compiler
ECS + C# Job System + BurstCompiler
Запрофайлил, и сразу в глаза бросается .NET Memory Allocations почти 4GB, что много для такой гифки (все кадры в 32 bit цвете без сжатия — 64MB).

Я думаю после оптимизации аллокаций всё станет достаточно быстро без многопоточности и где угодно.
Нужно:
— Указывать capacity для коллекций при инициализации
— Заменить ключ словаря со String на что-нибудь более легковесное
— Очень желательно не использовать LINQ с тысячами элементов
largeArray.Contains(1)
У массива нет метода Contains, это LINQ метод. Соответственно результаты зависят от реализации LINQ и оптимизатора.
Более правильный вариант:
Array.IndexOf(largeArray, 1) != -1
smooth.foundations
Но в вашем случае лучше использовать IndexOf дабы не добавлять зависимости
может быть компилятор C# оптимизирует вызов метода Contains(1) в цикле, так как в нем константа?
я бы попробовал Contains(i)
Часто говорят, что Unity медленный.
Простите, что вмешиваюсь в технические споры, но с точки зрения достаточно поигравшего в игры на юнити человека, меня удивляет, что графика по виду времен 2008 года (quern — самое пристойное из сыгранного) и ранее, может лагать на современных видеокартах. Непонятно, почему не делать игры на оптимизированных движках, UE, например. Я без претензий к качеству игр, встречаются и хорошие (к слову, очень понравилась Lifeless Planet), вопросы к просто убогой производительности. Получаешь, грубо говоря, солитер, жрущий как крузис какой-нибудь.
Вспомните старые приложения на дельфи которые висли при нажатии на кнопочку обновить, потому что UI тред блокировался пока идет ответ от базы.
В Unity все пользовательские скрипты отрабатывают в промежутках между кадрами. Чтобы получить ровные 60fps, нужно размазать нагрузку ровным слоем по всем промежуткам (~16мс) между кадрами. Это довольно сложно сделать. Соответственно чуть промахнулся — лови фриз.
Простите, что натолкнул на такую мысль, но я не для холивара спрашивал. Во время игры все время интересовало, чем юнити предпочтительнее UE (у того тоже насколько я знаю, бесплатная версия есть), но не у кого было спросить. После собственно игры как-то тема уже переставала быть актуальной и на серьёзные исследования и сравнения меня уже не хватало. Прочитал, вспомнил игровой опыт, немного поплакал и решил спросить у бывалых.
Теперь буду загадывать на Новый год, чтобы все разработчики игр освоили c++.Мой друг, отличный С++ гейм-девелопер утверждает, что даже хорошо зная язык на C# писать проще и быстрее, особенно если ты инди.
Как архитектурное решение для всей игры оно не подходит, а подходит только для управления и визуализации однотипных 3д объектов(здесь огромный приток производительности), при попытке заюзать её для спрайтовых объектов, вас ждёт конфуз, и гугление решений использования спрайтов
Как говорил дедушка Ленин, — «Практика критерий истины»
Крайне успешно использую собственный ECS с расширениями в своем домашнем велосипеде (не на юнити).
Честно говоря, не знаю что за проблемы у Unity со спрайтами и чем они вообще могут мешать ECS'у. И почему 3д-объекты в этом плане должны отличаться от спрайтовых.
Хотя бы потому, что нужна писать в несколько раз больше кода, а пальцы, они знаете, не казенные :)
Юзал LeoECS для три в ряд — получил меньше кода чем в обычной реализации, что я сделал не так?
с новых beta версий Unity постепенно переходит на ECSРазговор шел о реализации усов в юнити. Напишите свой шедевр используя
… что усы, что джобсыот юнитеков, сразу себя почувствуете великим писателем. Ну и а если по существу, то у меня нет оснований вам верить на слово, мозоли на пальцах не дают. К коду систем, которые были бы, скажем контроллерами, в случае «стандартного» подхода, у вас неизбежно добавилась кучка компонентов для сущностей. Это первое, что приходит в голову. Количество систем, наверняка несоизмеримо с количеством контроллеров, при том же «стандартном» подходе. Вы еще на энтитас попробуйте там еще один приятный + в виде кодогенерации. С платной версией с рослином еще сносно, но без него рефактор превращается в попаболь ) И поймите меня правильно, что я вовсе не противник усов, я даже за, но не оголтело, как сейчас народ кинулся, а с умом, там где это уместно. Ну реально, есть более красивые решения. Вас не напрягает, что в усах очень высокий процент холостого хода? Потому как запрошенные вами сущности (набор компонентов) ищутся в каждом кадре. Есть они, нет их, контейнер пытается их найти в неком списке. То есть идет ненужное итерирование. Это конечно не смертельно, можно и забить, но мой перфекционизм не дает мне спать ) Попробуйте повозится не с псевдособытийной, а с реально событийной моделью архитектуры.
у меня нет оснований вам верить на слово
Я тут согласен, для подобных дискуссий нужно(мне) запилить проект и говорить по существу.
И поймите меня правильно, что я вовсе не противник усов, я даже за, но не оголтело, как сейчас народ кинулся, а с умом, там где это уместно.
Я тоже за продуманное использование. Оголтело их советуют, те кто с ними не особо работал. Налепить неоптимального говнокода можно в рамках любой архитектуры, в этой архитектуре наказание за говнокод может прийти моментально.
«Попробуйте повозится не с псевдособытийной, а с реально событийной моделью архитектуры.» Я использовал разные архитектуры(8лет на флеше), а там событийный подход из коробки.
ECS мне нравиться тем, что это, по сути, конвейерная лента по которой перемещаются сущности, а система это, типа обрабатывающий станок. Это даёт огромную гибкость в расширении и написании кода. И, да кодогенерация, которая позволяет переложить часть работы на геймдизов.
Второй момент, легко отлаживать, так как визуализатор контейнера сущностей с состояними компонентов в редакторе юнити, даёт хорошее представлени о том, что происходит с данными в рантайме.
Т.е. легко локализовать ошибку.
Как минус, холостой ход и выборки.
На самом деле, не всегда.
Хороший компилятор С++ (Visual C, GCC) обычно генерирует код лучше, чем если писать вручную.
Плюс может использовать SSE/AVX инструкции.
Результат для меня довольно загадочный. Не вижу особых отличий между Linq и другим кодом чтобы он так тормозил (в сотни раз). Кто прояснит причину?
Действительно ли Unity медленный? Осторожно, LINQ