using NUnit.Framework;
using Unity.Collections;
using Unity.PerformanceTesting;
using UnityEditor.UIElements;
namespace Unity.Entities.PerformanceTests
{
[TestFixture]
[Category("Performance")]
public sealed class DynamicBufferPerformanceTests
{
World m_PreviousWorld;
World m_World;
EntityManager m_Manager;
EntityQuery group;
private const int kLargeAllocation = 32 * 1024 * 1024 / sizeof(int);
private const int kSmallAllocation = 1 * 1024 / sizeof(int);
private const int kTinyAllocation = 4;
///
/// To get a reasonable reading from the tiny and small tests we need to run the code a lot more.
///
private const int kTimesToCopyInManyTest = 10000;
private NativeArray nativeArrayLarge;
private NativeArray nativeArraySmall;
private NativeArray nativeArrayTiny;
private EcsIntElement[] arrayLarge;
private EcsIntElement[] arraySmall;
private EcsIntElement[] arrayTiny;
[SetUp]
public void Setup()
{
m_PreviousWorld = World.Active;
m_World = World.Active = new World("Test World");
m_Manager = m_World.EntityManager;
nativeArrayLarge = new NativeArray(kLargeAllocation, Allocator.Persistent);
nativeArraySmall = new NativeArray(kSmallAllocation, Allocator.Persistent);
nativeArrayTiny = new NativeArray(kTinyAllocation, Allocator.Persistent);
arrayLarge = new EcsIntElement[kLargeAllocation];
arraySmall = new EcsIntElement[kSmallAllocation];
arrayTiny = new EcsIntElement[kTinyAllocation];
for (var i = 0; i < kLargeAllocation; ++i)
{
if (i < kTinyAllocation)
{
nativeArrayTiny[i] = i;
arrayTiny[i] = i;
}
if (i < kSmallAllocation)
{
nativeArraySmall[i] = i;
arraySmall[i] = i;
}
nativeArrayLarge[i] = i;
arrayLarge[i] = i;
}
}
[TearDown]
public void TearDown()
{
if (m_Manager != null)
{
m_World.Dispose();
m_World = null;
World.Active = m_PreviousWorld;
m_PreviousWorld = null;
m_Manager = null;
}
nativeArrayLarge.Dispose();
nativeArraySmall.Dispose();
nativeArrayTiny.Dispose();
}
public struct EcsIntElement : IBufferElementData
{
public static implicit operator int(EcsIntElement e)
{
return e.Value;
}
public static implicit operator EcsIntElement(int e)
{
return new EcsIntElement {Value = e};
}
public int Value;
}
#if UNITY_2019_2_OR_NEWER
[Test, Performance]
#else
[PerformanceTest]
#endif
public void CopyFromDynamicBuffer()
{
var e = m_Manager.CreateEntity();
var f = m_Manager.CreateEntity();
m_Manager.AddBuffer(e);
m_Manager.AddBuffer(f);
var src = m_Manager.GetBuffer(e);
var dst = m_Manager.GetBuffer(f);
src.Reserve(kTinyAllocation);
dst.Reserve(kTinyAllocation);
for (var i = 0; i < kTinyAllocation; ++i)
{
src.Add(1);
dst.Add(2);
}
Measure.Method(
() =>
{
for(var i = 0; i < kTimesToCopyInManyTest; ++i)
dst.CopyFrom(src);
})
.Definition("Tiny")
.WarmupCount(100)
.MeasurementCount(500)
.Run();
src.Reserve(kSmallAllocation);
dst.Reserve(kSmallAllocation);
for (var i = kTinyAllocation; i < kSmallAllocation; ++i)
{
src.Add(1);
dst.Add(2);
}
Measure.Method(
() =>
{
for(var i = 0; i < kTimesToCopyInManyTest; ++i)
dst.CopyFrom(src);
})
.Definition("Small")
.WarmupCount(100)
.MeasurementCount(500)
.Run();
src.Reserve(kLargeAllocation);
dst.Reserve(kLargeAllocation);
for (var i = kSmallAllocation; i < kLargeAllocation; ++i)
{
src.Add(1);
dst.Add(2);
}
Measure.Method(
() =>
{
dst.CopyFrom(src);
})
.Definition("Large")
.WarmupCount(100)
.MeasurementCount(500)
.Run();
m_Manager.DestroyEntity(e);
m_Manager.DestroyEntity(f);
}
#if UNITY_2019_2_OR_NEWER
[Test, Performance]
#else
[PerformanceTest]
#endif
public void CopyFromNativeArray()
{
var e = m_Manager.CreateEntity();
m_Manager.AddBuffer(e);
var dst = m_Manager.GetBuffer(e);
dst.Reserve(kTinyAllocation);
for (var i = 0; i < kTinyAllocation; ++i)
{
dst.Add(0);
}
Measure.Method(
() =>
{
for(var i = 0; i < kTimesToCopyInManyTest; ++i)
dst.CopyFrom(nativeArrayTiny);
})
.Definition("Tiny")
.WarmupCount(100)
.MeasurementCount(500)
.Run();
dst.Reserve(kSmallAllocation);
for (var i = kTinyAllocation; i < kSmallAllocation; ++i)
{
dst.Add(1);
}
Measure.Method(
() =>
{
for(var i = 0; i < kTimesToCopyInManyTest; ++i)
dst.CopyFrom(nativeArraySmall);
})
.Definition("Small")
.WarmupCount(100)
.MeasurementCount(500)
.Run();
dst.Reserve(kLargeAllocation);
for (var i = kSmallAllocation; i < kLargeAllocation; ++i)
{
dst.Add(2);
}
Measure.Method(
() =>
{
dst.CopyFrom(nativeArrayLarge);
})
.Definition("Large")
.WarmupCount(100)
.MeasurementCount(500)
.Run();
m_Manager.DestroyEntity(e);
}
#if UNITY_2019_2_OR_NEWER
[Test, Performance]
#else
[PerformanceTest]
#endif
public void CopyFromArray()
{
var e = m_Manager.CreateEntity();
m_Manager.AddBuffer(e);
var dst = m_Manager.GetBuffer(e);
dst.Reserve(kTinyAllocation);
for (var i = 0; i < kTinyAllocation; ++i)
{
dst.Add(0);
}
Measure.Method(
() =>
{
for(var i = 0; i < kTimesToCopyInManyTest; ++i)
dst.CopyFrom(arrayTiny);
})
.Definition("Tiny")
.WarmupCount(100)
.MeasurementCount(500)
.Run();
dst.Reserve(kSmallAllocation);
for (var i = kTinyAllocation; i < kSmallAllocation; ++i)
{
dst.Add(1);
}
Measure.Method(
() =>
{
for(var i = 0; i < kTimesToCopyInManyTest; ++i)
dst.CopyFrom(arraySmall);
})
.Definition("Small")
.WarmupCount(100)
.MeasurementCount(500)
.Run();
dst.Reserve(kLargeAllocation);
for (var i = kSmallAllocation; i < kLargeAllocation; ++i)
{
dst.Add(2);
}
Measure.Method(
() =>
{
dst.CopyFrom(arrayLarge);
})
.Definition("Large")
.WarmupCount(100)
.MeasurementCount(500)
.Run();
m_Manager.DestroyEntity(e);
}
}
}