Hello,
I tried to figure out how the unity job system works and when to use it. I made a basic performance test doing one million calculations using four different methods: TestMe1A(), TestMe1B(), TestMe2() and TestMe3(). They take 1300ms, 2000ms, 4ms and 17ms and lead to the same output. The amount of time taken by the last Method (TestMe3()), where no job has been used is remarkable.
Because of the variety of the amount of time taken, my basic questions are if there is anything wrong with my code and how to know which way to choose, particularly with regard to three different IJob Methods.
Here is the code:
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst;
public class StartGame : MonoBehaviour
{
private Stopwatch stopwatch;
// Start is called before the first frame update
void Start()
{
stopwatch = new Stopwatch();
TestMe1A();
TestMe1B();
TestMe2();
TestMe3();
}
int num = 1000000;
// IJob
public void TestMe1A()
{
stopwatch.Start();
NativeArray<float> _results = new NativeArray<float>(num, Allocator.Temp);
JobHandle jH = new JobHandle();
for (int i = 0; i < num; i++)
{
float _a = i;
float _b = i + 1;
float _c = 0;
TestJob theJob = new TestJob
{
results = _results,
a = _a,
b = _b,
c = _c,
i = i,
};
jH = theJob.Schedule();
}
jH.Complete();
stopwatch.Stop();
UnityEngine.Debug.LogFormat("IJob completed after {0} ms. The results: {1}", stopwatch.ElapsedMilliseconds, string.Join(", ", _results)); // 1300+ ms
stopwatch.Reset();
_results.Dispose();
}
// IJob Array
public void TestMe1B()
{
stopwatch.Start();
NativeArray<float> _results = new NativeArray<float>(num, Allocator.Temp);
NativeArray<JobHandle> jobHandleArray = new NativeArray<JobHandle>(num, Allocator.Temp);
for (int i = 0; i < num; i++)
{
float _a = i;
float _b = i + 1;
float _c = 0;
TestJob theJob = new TestJob
{
results = _results,
a = _a,
b = _b,
c = _c,
i = i,
};
jobHandleArray[i] = theJob.Schedule();
}
JobHandle.CompleteAll(jobHandleArray);
stopwatch.Stop();
UnityEngine.Debug.LogFormat("IJob Array completed after {0} ms. The results: {1}", stopwatch.ElapsedMilliseconds, string.Join(", ", _results)); // 2000+ ms
stopwatch.Reset();
jobHandleArray.Dispose();
_results.Dispose();
}
// IJobParallelFor
public void TestMe2()
{
stopwatch.Start();
NativeArray<float> _results_ = new NativeArray<float>(num, Allocator.Temp);
JobHandle jobHandle = new JobHandle();
TestJob2 theJob2 = new TestJob2
{
results = _results_,
};
jobHandle = theJob2.Schedule(num, 64);
jobHandle.Complete();
stopwatch.Stop();
UnityEngine.Debug.LogFormat("IJobParallelFor completed after {0} ms. The results: {1}", stopwatch.ElapsedMilliseconds, string.Join(", ", _results_)); // 4+ ms
stopwatch.Reset();
_results_.Dispose();
}
// No Job
public void TestMe3()
{
stopwatch.Start();
float[] theResults = new float[num];
for (int i = 0; i < num; i++)
{
float _a = i;
float _b = i + 1;
float _c = _a / _b;
theResults[i] = _c;
}
stopwatch.Stop();
UnityEngine.Debug.LogFormat("NoJob completed after {0} ms. The results: {1}", stopwatch.ElapsedMilliseconds, string.Join(", ", theResults)); // 17+ ms
stopwatch.Reset();
}
[BurstCompile]
public struct TestJob : IJob
{
public NativeArray<float> results;
public float a;
public float b;
public float c;
public int i;
public void Execute()
{
c = a / b;
results[i] = c;
}
}
[BurstCompile]
public struct TestJob2 : IJobParallelFor
{
public NativeArray<float> results;
public void Execute(int i)
{
float a = i;
float b = i + 1;
float c;
c = a / b;
results[i] = c;
}
}
}
Thanks for your feedback!