A game about forced loneliness, made by TACStudios
at master 246 lines 9.0 kB view raw
1using NUnit.Framework; 2using UnityEngine; 3using Unity.Collections.LowLevel.Unsafe; 4using Unity.PerformanceTesting; 5using Unity.PerformanceTesting.Benchmark; 6using System.Runtime.CompilerServices; 7using System.Threading; 8 9namespace Unity.Collections.PerformanceTests 10{ 11 static class RingQueueUtil 12 { 13 static public void AllocInt(ref NativeRingQueue<int> container, int capacity, bool addValues) 14 { 15 if (capacity >= 0) 16 { 17 Random.InitState(0); 18 container = new NativeRingQueue<int>(capacity, Allocator.Persistent); 19 if (addValues) 20 { 21 for (int i = 0; i < capacity; i++) 22 container.Enqueue(i); 23 } 24 } 25 else 26 container.Dispose(); 27 } 28 static public void AllocInt(ref UnsafeRingQueue<int> container, int capacity, bool addValues) 29 { 30 if (capacity >= 0) 31 { 32 Random.InitState(0); 33 container = new UnsafeRingQueue<int>(capacity, Allocator.Persistent); 34 if (addValues) 35 { 36 for (int i = 0; i < capacity; i++) 37 container.Enqueue(i); 38 } 39 } 40 else 41 container.Dispose(); 42 } 43 static public object AllocBclContainer(int capacity, bool addValues) 44 { 45 if (capacity < 0) 46 return null; 47 48 Random.InitState(0); 49 var bclContainer = new System.Collections.Generic.Queue<int>(capacity); 50 if (addValues) 51 { 52 for (int i = 0; i < capacity; i++) 53 bclContainer.Enqueue(i); 54 } 55 return bclContainer; 56 } 57 58 static public void CreateRandomValues(int capacity, ref UnsafeList<int> values) 59 { 60 if (capacity >= 0) 61 { 62 values = new UnsafeList<int>(capacity, Allocator.Persistent); 63 Random.InitState(0); 64 for (int i = 0; i < capacity; i++) 65 { 66 int randKey = Random.Range(0, capacity); 67 values.Add(randKey); 68 } 69 } 70 else 71 values.Dispose(); 72 } 73 } 74 75 struct RingQueueIsEmpty100k : IBenchmarkContainer 76 { 77 const int kIterations = 100_000; 78 NativeRingQueue<int> nativeContainer; 79 UnsafeRingQueue<int> unsafeContainer; 80 81 public void AllocNativeContainer(int capacity) => RingQueueUtil.AllocInt(ref nativeContainer, capacity, true); 82 public void AllocUnsafeContainer(int capacity) => RingQueueUtil.AllocInt(ref unsafeContainer, capacity, true); 83 public object AllocBclContainer(int capacity) => RingQueueUtil.AllocBclContainer(capacity, true); 84 85 [MethodImpl(MethodImplOptions.NoOptimization)] 86 public void MeasureNativeContainer() 87 { 88 for (int i = 0; i < kIterations; i++) 89 _ = nativeContainer.IsEmpty; 90 } 91 [MethodImpl(MethodImplOptions.NoOptimization)] 92 public void MeasureUnsafeContainer() 93 { 94 for (int i = 0; i < kIterations; i++) 95 _ = unsafeContainer.IsEmpty; 96 } 97 [MethodImpl(MethodImplOptions.NoOptimization)] 98 public void MeasureBclContainer(object container) 99 { 100 var bclContainer = (System.Collections.Generic.Queue<int>)container; 101 for (int i = 0; i < kIterations; i++) 102 _ = bclContainer.Count == 0; 103 } 104 } 105 106 struct RingQueueCount100k : IBenchmarkContainer 107 { 108 const int kIterations = 100_000; 109 NativeRingQueue<int> nativeContainer; 110 UnsafeRingQueue<int> unsafeContainer; 111 112 public void AllocNativeContainer(int capacity) => RingQueueUtil.AllocInt(ref nativeContainer, capacity, true); 113 public void AllocUnsafeContainer(int capacity) => RingQueueUtil.AllocInt(ref unsafeContainer, capacity, true); 114 public object AllocBclContainer(int capacity) => RingQueueUtil.AllocBclContainer(capacity, true); 115 116 [MethodImpl(MethodImplOptions.NoOptimization)] 117 public void MeasureNativeContainer() 118 { 119 for (int i = 0; i < kIterations; i++) 120 _ = nativeContainer.Length; 121 } 122 [MethodImpl(MethodImplOptions.NoOptimization)] 123 public void MeasureUnsafeContainer() 124 { 125 for (int i = 0; i < kIterations; i++) 126 _ = unsafeContainer.Length; 127 } 128 [MethodImpl(MethodImplOptions.NoOptimization)] 129 public void MeasureBclContainer(object container) 130 { 131 var bclContainer = (System.Collections.Generic.Queue<int>)container; 132 for (int i = 0; i < kIterations; i++) 133 _ = bclContainer.Count; 134 } 135 } 136 137 struct RingQueueEnqueue : IBenchmarkContainer 138 { 139 int capacity; 140 NativeRingQueue<int> nativeContainer; 141 UnsafeRingQueue<int> unsafeContainer; 142 143 void IBenchmarkContainer.SetParams(int capacity, params int[] args) => this.capacity = capacity; 144 145 public void AllocNativeContainer(int capacity) => RingQueueUtil.AllocInt(ref nativeContainer, capacity, false); 146 public void AllocUnsafeContainer(int capacity) => RingQueueUtil.AllocInt(ref unsafeContainer, capacity, false); 147 public object AllocBclContainer(int capacity) => RingQueueUtil.AllocBclContainer(capacity, false); 148 149 public void MeasureNativeContainer() 150 { 151 for (int i = 0; i < capacity; i++) 152 nativeContainer.Enqueue(i); 153 } 154 public void MeasureUnsafeContainer() 155 { 156 for (int i = 0; i < capacity; i++) 157 unsafeContainer.Enqueue(i); 158 } 159 public void MeasureBclContainer(object container) 160 { 161 var bclContainer = (System.Collections.Generic.Queue<int>)container; 162 for (int i = 0; i < capacity; i++) 163 bclContainer.Enqueue(i); 164 } 165 } 166 167 struct RingQueueDequeue : IBenchmarkContainer 168 { 169 int capacity; 170 NativeRingQueue<int> nativeContainer; 171 UnsafeRingQueue<int> unsafeContainer; 172 173 void IBenchmarkContainer.SetParams(int capacity, params int[] args) => this.capacity = capacity; 174 175 public void AllocNativeContainer(int capacity) => RingQueueUtil.AllocInt(ref nativeContainer, capacity, true); 176 public void AllocUnsafeContainer(int capacity) => RingQueueUtil.AllocInt(ref unsafeContainer, capacity, true); 177 public object AllocBclContainer(int capacity) => RingQueueUtil.AllocBclContainer(capacity, true); 178 179 public void MeasureNativeContainer() 180 { 181 int keep = 0; 182 for (int i = 0; i < capacity; i++) 183 Volatile.Write(ref keep, nativeContainer.Dequeue()); 184 } 185 public void MeasureUnsafeContainer() 186 { 187 int keep = 0; 188 for (int i = 0; i < capacity; i++) 189 Volatile.Write(ref keep, unsafeContainer.Dequeue()); 190 } 191 public void MeasureBclContainer(object container) 192 { 193 int keep = 0; 194 var bclContainer = (System.Collections.Generic.Queue<int>)container; 195 for (int i = 0; i < capacity; i++) 196 Volatile.Write(ref keep, bclContainer.Dequeue()); 197 } 198 } 199 200 [Benchmark(typeof(BenchmarkContainerType))] 201 [BenchmarkNameOverride(BenchmarkContainerConfig.BCL, "Queue")] 202 class RingQueue 203 { 204#if UNITY_EDITOR 205 [UnityEditor.MenuItem(BenchmarkContainerConfig.kMenuItemIndividual + nameof(RingQueue))] 206 static void RunIndividual() 207 => BenchmarkContainerConfig.RunBenchmark(typeof(RingQueue)); 208#endif 209 210 [Test, Performance] 211 [Category("Performance")] 212 public unsafe void IsEmpty_x_100k( 213 [Values(0, 100)] int capacity, 214 [Values] BenchmarkContainerType type) 215 { 216 BenchmarkContainerRunner<RingQueueIsEmpty100k>.Run(capacity, type); 217 } 218 219 [Test, Performance] 220 [Category("Performance")] 221 public unsafe void Count_x_100k( 222 [Values(0, 100)] int capacity, 223 [Values] BenchmarkContainerType type) 224 { 225 BenchmarkContainerRunner<RingQueueCount100k>.Run(capacity, type); 226 } 227 228 [Test, Performance] 229 [Category("Performance")] 230 public unsafe void Enqueue( 231 [Values(10000, 100000, 1000000)] int insertions, 232 [Values] BenchmarkContainerType type) 233 { 234 BenchmarkContainerRunner<RingQueueEnqueue>.Run(insertions, type); 235 } 236 237 [Test, Performance] 238 [Category("Performance")] 239 public unsafe void Dequeue( 240 [Values(10000, 100000, 1000000)] int insertions, 241 [Values] BenchmarkContainerType type) 242 { 243 BenchmarkContainerRunner<RingQueueDequeue>.Run(insertions, type); 244 } 245 } 246}