Last active
April 2, 2020 18:01
-
-
Save jeffvella/b4c3dc2b6748d62dab6dca6e6bcad780 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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)] 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