Skip to content

Instantly share code, notes, and snippets.

@jeffvella
Created April 2, 2020 18:16
Show Gist options
  • Select an option

  • Save jeffvella/ad499fb3e1d6642f30f08dfd36a63dc8 to your computer and use it in GitHub Desktop.

Select an option

Save jeffvella/ad499fb3e1d6642f30f08dfd36a63dc8 to your computer and use it in GitHub Desktop.
using NUnit.Framework;
using System;
using System.Diagnostics;
using System.Linq;
using Unity.Collections;
using Unity.Entities;
using Unity.PerformanceTesting;
namespace Packages.com.vella.events.Tests
{
public class SimpleTestFixture
{
protected World m_PreviousWorld;
protected World m_World;
protected EntityManager m_Manager;
[SetUp]
virtual public void Setup()
{
m_PreviousWorld = World.DefaultGameObjectInjectionWorld;
m_World = World.DefaultGameObjectInjectionWorld = new World("Test World");
m_Manager = m_World.EntityManager;
}
[TearDown]
virtual public void TearDown()
{
if (m_Manager != null)
{
m_World.Dispose();
m_World = null;
World.DefaultGameObjectInjectionWorld = m_PreviousWorld;
m_PreviousWorld = null;
m_Manager = null;
}
}
}
public struct ComparisonTestData2 : IComponentData
{
public int value;
}
public struct ComparisonTestData1 : IComponentData
{
public int value;
}
public class IsolatedComparison2 : SimpleTestFixture
{
[Test, Performance]
public void CompareDefaultApproaches2([Values(1, 25, 100, 250, 1000)] int eventsPerArchetype)
{
var system1 = m_World.GetOrCreateSystem<EventComparisonTestSystem>();
system1.EventsPerArchetype = eventsPerArchetype;
system1.Update();
}
[DisableAutoCreation]
public class EventComparisonTestSystem : SystemBase
{
public int Measurements = 50;
public int Warmups = 5;
public int EventsPerArchetype = 25;
public NativeList<Entity> EntityBuffer;
public SampleGroupDefinition Group;
public EntityQuery Query;
public EntityArchetype Archetype;
public Stopwatch StopWatch;
protected override void OnCreate()
{
Group = new SampleGroupDefinition
{
AggregationType = AggregationType.Average,
Name = "Unnamed",
SampleUnit = SampleUnit.Millisecond
};
StopWatch = new Stopwatch();
var components = new[]
{
ComponentType.ReadWrite<ComparisonTestData1>(),
ComponentType.ReadWrite<ComparisonTestData2>(),
};
Archetype = EntityManager.CreateArchetype(components);
Query = EntityManager.CreateEntityQuery(components);
var groupA = new SampleGroupDefinition
{
AggregationType = AggregationType.Average,
Name = "Default",
SampleUnit = SampleUnit.Millisecond
};
EntityBuffer = new NativeList<Entity>(EventsPerArchetype, Allocator.Temp);
}
public enum CreationMethod2
{
None = 0,
IndividualArchetype,
NativeArrayArchetype,
CreateAndSetComponents,
ECB_Individual,
ECB_IndividualBurst,
}
public enum DestructionMethod
{
None = 0,
IndividualEntity,
WithQuery,
WithNativeArray,
ECB_WithQuery,
ECB_Individual,
ECB_IndividualBurst,
}
public struct Combination : IEquatable<Combination>
{
public CreationMethod2 CreationType;
public DestructionMethod DestructionType;
public bool Equals(Combination other)
{
return other.CreationType == CreationType && other.DestructionType == DestructionType;
}
public override int GetHashCode()
{
int hash = 13;
hash = (hash * 7) + CreationType.GetHashCode();
hash = (hash * 7) + DestructionType.GetHashCode();
return hash;
}
}
protected override void OnUpdate()
{
var entities = EntityBuffer;
var archetype = Archetype;
var creationMethods = Enum.GetValues(typeof(CreationMethod2)).Cast<CreationMethod2>();
var destructionMethods = Enum.GetValues(typeof(DestructionMethod)).Cast<DestructionMethod>();
var combinations = creationMethods.SelectMany(a => destructionMethods.Select(b => new Combination
{
CreationType = a,
DestructionType = b,
})).Distinct().ToList();
foreach (var combination in combinations)
{
Group.Name = $"Create: {combination.CreationType}, Destroy: {combination.DestructionType}";
EntityManager.DestroyEntity(Query);
for (int i = 0; i < Measurements; i++)
{
entities.ResizeUninitialized(UnityEngine.Random.Range(1, EventsPerArchetype));
EntityManager.CreateEntity(archetype, entities);
// Seems to crash he editor if you create and delete from the same ECB.
var creationECB = new EntityCommandBuffer(Allocator.Temp);
var destructionECB = new EntityCommandBuffer(Allocator.Temp);
if (i < Warmups)
{
Test(combination, entities, archetype, Query, creationECB, destructionECB);
}
else
{
StopWatch.Restart();
Test(combination, entities, archetype, Query, creationECB, destructionECB);
StopWatch.Stop();
Measure.Custom(Group, StopWatch.Elapsed.TotalMilliseconds);
}
}
}
}
private void Test(Combination combination, NativeList<Entity> entities, EntityArchetype archetype, EntityQuery query, EntityCommandBuffer creationECB, EntityCommandBuffer destructionECB)
{
switch (combination.DestructionType)
{
case DestructionMethod.IndividualEntity:
for (int i = 0; i < entities.Length; i++)
{
EntityManager.DestroyEntity(entities[i]);
}
break;
case DestructionMethod.WithQuery:
EntityManager.DestroyEntity(query);
break;
case DestructionMethod.WithNativeArray:
EntityManager.DestroyEntity(entities);
break;
case DestructionMethod.ECB_WithQuery:
destructionECB.DestroyEntity(query);
destructionECB.Playback(EntityManager);
break;
case DestructionMethod.ECB_Individual:
for (int i = 0; i < entities.Length; i++)
{
destructionECB.DestroyEntity(entities[i]);
}
destructionECB.Playback(EntityManager);
break;
case DestructionMethod.ECB_IndividualBurst:
Job.WithCode(() =>
{
for (int i = 0; i < entities.Length; i++)
{
destructionECB.DestroyEntity(entities[i]);
}
}).Run();
destructionECB.Playback(EntityManager);
break;
}
switch (combination.CreationType)
{
case CreationMethod2.IndividualArchetype:
for (int i = 0; i < entities.Length; i++)
{
EntityManager.CreateEntity(archetype);
}
break;
case CreationMethod2.NativeArrayArchetype:
EntityManager.CreateEntity(archetype, entities);
break;
case CreationMethod2.CreateAndSetComponents:
for (int i = 0; i < entities.Length; i++)
{
var entity = EntityManager.CreateEntity();
EntityManager.AddComponent<ComparisonTestData2>(entity);
EntityManager.AddComponent<ComparisonTestData1>(entity);
}
break;
case CreationMethod2.ECB_Individual:
for (int i = 0; i < entities.Length; i++)
{
creationECB.CreateEntity(archetype);
}
creationECB.Playback(EntityManager);
break;
case CreationMethod2.ECB_IndividualBurst:
Job.WithCode(() =>
{
for (int i = 0; i < entities.Length; i++)
{
creationECB.CreateEntity(archetype);
}
}).Run();
creationECB.Playback(EntityManager);
break;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment