Потоки в Unity3D — измеряем производительность

Привет!
Иногда меня спрашивают об отложенных действиях или о многопоточности в Unity3D и обычно я советую обратить внимание на класс Coroutine, благо он позволяет решать большинство повседневных задач, связанных с задержками и проч.
Однако, иногда при разработке действительно требуется настоящая многопоточность, при поиске пути, например.
Поэтому я решил сделать на скорую руку небольшой тест, в котором можно было бы пощупать многопоточность и сравнить производительность исполнения кода в одном (главном) потоке и в многопоточной реализации. Для начала я поискал какие-нибудь менеджеры потоков, чтобы не велосипедить и наткнулся на простецкий (но в моем случае, удобный) класс Loom от whydoidoit.

Далее я по-быстрому слепил приложение, скомпилировал его под разные платформы (в архиве в конце статьи есть бинарники для всех основных платформ и сорцы самого проекта) и посмотрел на результаты. . Некоторые мне показались интересными, поэтому я решим ими поделиться, может быть кому-то это будет полезно.

Вообще код, который пытался нагружать CPU прост как пробка — я просто пробегаюсь по приличному массиву экземпляров Vector3D (10 000 000 элементов под десктопами и 1 000 000 под мобилами):

private void Run()
{
const float scale = 432.654f;

for (int j = 0; j < arrayLength; j++)
{
Vector3 v = vertices[j];

v = Vector3.Lerp(v * scale / 123f * v.magnitude, v / scale * 0.0123f * v.magnitude, v.magnitude);

vertices[j] = v;
}
}

Как видите, «начинка» цикла по сути ничего конкретного не делает — просто случайный набор всяких медленных вещей)
Так же я добавил на сцену модельку муравья (привет создателям примеров для Away3D! :)), которая крутится каждый Update(), дабы можно было сразу увидеть — когда приложение подвисает, «задумываясь», а когда — нет.

JTMLjQ0

Как я ранее сказал, я провел некоторые тесты на подручном оборудовании, проверял скорость работы как в синхронном режиме (выполнение в главном потоке), так, и в асинхронном (массив бьется на столько равных частей, сколько ядер доступно приложению и каждая часть обрабатывается в отдельном потоке), и получил я такие результаты (S — синхр, A — асинхр):
Читать далее