Created
April 2, 2020 17:00
-
-
Save jeffvella/440bc24226431b231b2909d5f30d375f 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 IsolatedComparison : SimpleTestFixture | |
| { | |
| [Test, Performance] | |
| public void CompareDefaultApproaches([Values(1, 25, 100, 250, 1000, 5000)] 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 = "EntityCommandBuffer QueuedFromJob Destroyed Individually Inside Burst", | |
| 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 CreationMethod | |
| { | |
| None = 0, | |
| IndividualArchetype, | |
| NativeArrayArchetype, | |
| CreateAndSetComponents, | |
| ECB_NativeArrayArchetype, | |
| ECB_Individual, | |
| ECB_IndividualBurst, | |
| ECB_IndividualBurstQueued, | |
| } | |
| public enum DestructionMethod | |
| { | |
| None = 0, | |
| IndividualEntity, | |
| WithQuery, | |
| WithNativeArray, | |
| ECB_WithQuery, | |
| ECB_Individual, | |
| ECB_IndividualBurst, | |
| } | |
| public struct Combination : IEquatable<Combination> | |
| { | |
| public CreationMethod 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() | |
| { | |
| GC.TryStartNoGCRegion(1073741824); | |
| try | |
| { | |
| var entities = EntityBuffer; | |
| var archetype = Archetype; | |
| var creationMethods = Enum.GetValues(typeof(CreationMethod)).Cast<CreationMethod>().Skip(1); | |
| var destructionMethods = Enum.GetValues(typeof(DestructionMethod)).Cast<DestructionMethod>().Skip(1); | |
| 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); | |
| } | |
| } | |
| } | |
| } | |
| finally | |
| { | |
| GC.EndNoGCRegion(); | |
| } | |
| } | |
| 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 CreationMethod.IndividualArchetype: | |
| for (int i = 0; i < entities.Length; i++) | |
| { | |
| EntityManager.CreateEntity(archetype); | |
| } | |
| break; | |
| case CreationMethod.NativeArrayArchetype: | |
| EntityManager.CreateEntity(archetype, entities); | |
| break; | |
| case CreationMethod.CreateAndSetComponents: | |
| for (int i = 0; i < entities.Length; i++) | |
| { | |
| var entity = EntityManager.CreateEntity(); | |
| EntityManager.AddComponent<ComparisonTestData2>(entity); | |
| EntityManager.AddComponent<ComparisonTestData1>(entity); | |
| } | |
| break; | |
| case CreationMethod.ECB_NativeArrayArchetype: | |
| creationECB.CreateEntity(archetype); | |
| creationECB.Playback(EntityManager); | |
| break; | |
| case CreationMethod.ECB_Individual: | |
| for (int i = 0; i < entities.Length; i++) | |
| { | |
| creationECB.CreateEntity(archetype); | |
| } | |
| creationECB.Playback(EntityManager); | |
| break; | |
| case CreationMethod.ECB_IndividualBurstQueued: | |
| 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