← Назад к вопросам

Что такое Jobs?

2.4 Senior🔥 111 комментариев
#Асинхронность и многопоточность#Оптимизация

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Unity Jobs System?

Unity Jobs System — это высокопроизводительная система многопоточного программирования, встроенная в Unity, которая позволяет безопасно и эффективно распараллеливать вычисления, используя возможности современных многоядерных процессоров. Она является ключевым компонентом Data-Oriented Technology Stack (DOTS) и предназначена для устранения традиционных сложностей многопоточного кода, таких как состояние гонки, deadlock'и и необходимость вручную синхронизировать потоки.

Ключевые концепции и компоненты

  • Jobs (Задачи): Это единицы работы, которые можно выполнять параллельно. Вместо обычных классов C# для создания Job используется структура (struct), реализующая интерфейс IJob. Это позволяет избежать выделения памяти в управляемой куче (heap) и способствует кэшированию данных процессором.

    public struct VelocityJob : IJob
    {
        public float DeltaTime;
        public NativeArray<Vector3> Velocities;
        public NativeArray<Vector3> Positions;
    
        public void Execute()
        {
            for (int i = 0; i < Positions.Length; i++)
            {
                Positions[i] = Positions[i] + Velocities[i] * DeltaTime;
            }
        }
    }
    
  • NativeContainer (Нативные контейнеры): Это обёртки над нативной (неуправляемой) памятью, которые обеспечивают безопасный доступ к данным из Job. Самый распространённый контейнер — NativeArray<T>. Он предоставляет семантику, похожую на массив C#, но выделяет память во временном аллокаторе (например, Allocator.TempJob), что минимизирует сборку мусора (Garbage Collection). Для параллельной записи в массив из нескольких Job существует NativeArray<T>.Concurrent.

  • Job Dependencies (Зависимости Job): Система автоматически отслеживает зависимости между Job на основе используемых NativeContainer. Если одна Job читает или пишет в NativeArray, а другая Job планирует запись в тот же массив, система JobSystem создаст зависимость и запустит вторую Job только после завершения первой. Это избавляет разработчика от ручного управления примитивами синхронизации.

  • JobHandle: Объект, представляющий собой "ссылку" на запланированную Job. С помощью JobHandle можно:

    *   Дожидаться завершения Job (`.Complete()`).
    *   Объединять зависимости нескольких Job с помощью `JobHandle.CombineDependencies()`.
    *   Передавать зависимости между Job.

```csharp
// Планирование и управление зависимостями
JobHandle firstJobHandle = firstJob.Schedule();
JobHandle secondJobHandle = secondJob.Schedule(dependsOn: firstJobHandle);

// Ожидание завершения всех зависимых Job
secondJobHandle.Complete();

// Теперь можно безопасно читать результаты из NativeArray в основном потоке
```
  • Parallel Jobs (Параллельные Job): Для задач, которые можно легко разделить на независимые части (например, обработка тысяч объектов), используются интерфейсы IJobParallelFor или IJobParallelForTransform. Система автоматически распределит итерации цикла Execute(int index) по доступным ядрам процессора.

    public struct MoveParallelJob : IJobParallelFor
    {
        public NativeArray<Vector3> Positions;
        public Vector3 MoveVector;
    
        public void Execute(int index)
        {
            // Каждая итерация обрабатывает свой элемент массива
            Positions[index] += MoveVector;
        }
    }
    // Планирование с указанием длины массива и размера пакета (batch size)
    JobHandle handle = moveJob.Schedule(Positions.Length, 64);
    

Преимущества использования Jobs System

  • Производительность: Значительный прирост скорости за счёт использования всех ядер CPU для таких задач, как анимация, физика, обработка частиц, генерация мешей и сложные математические вычисления.
  • Безопасность: Встроенная система зависимостей на основе данных предотвращает большинство ошибок параллелизма. Компилятор и Burst Compiler также предоставляют дополнительные проверки.
  • Эффективное использование памяти: Использование структур (struct) и NativeContainer минимизирует аллокации в управляемой куче, снижая нагрузку на Garbage Collector и уменьшая просадки FPS.
  • Предсказуемость: Позволяет создавать более предсказуемый по производительности код, что критически важно для игр с фиксированным временем шага (fixed-timestep) или для мобильных платформ.

Важные ограничения и правила

  • Job-структуры не могут содержать ссылочные типы (обычные классы C#). Данные должны передаваться через типы значений (int, float, struct) или NativeContainer.
  • Доступ к результатам NativeContainer из основного потока возможен только после вызова JobHandle.Complete() для всех зависимых Job.
  • NativeContainer, созданные с Allocator.TempJob, должны быть уничтожены (Dispose()) в том же потоке, где были созданы, и до завершения кадра.
  • Job нельзя планировать изнутри другой Job. Планирование происходит только из основного потока или из запланированного, но ещё не запущенного Job.

Таким образом, Jobs System — это мощный инструмент для оптимизации, который требует перехода от объектно-ориентированного стиля к данно-ориентированному (Data-Oriented), но взамен предоставляет беспрецедентный контроль над многопоточностью и производительностью в Unity.