A game about forced loneliness, made by TACStudios
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 ArrayUtil 12 { 13 static public void AllocInt(ref NativeArray<int> container, int capacity, bool addValues) 14 { 15 if (capacity >= 0) 16 { 17 Random.InitState(0); 18 container = new NativeArray<int>(capacity, Allocator.Persistent); 19 if (addValues) 20 { 21 for (int i = 0; i < capacity; i++) 22 container[i] = i; 23 } 24 } 25 else 26 container.Dispose(); 27 } 28 static public object AllocBclContainer(int capacity, bool addValues) 29 { 30 if (capacity < 0) 31 return null; 32 33 Random.InitState(0); 34 var bclContainer = new int[capacity]; 35 if (addValues) 36 { 37 for (int i = 0; i < capacity; i++) 38 bclContainer[i] = i; 39 } 40 return bclContainer; 41 } 42 43 static public void CreateRandomValues(int capacity, ref UnsafeList<int> values) 44 { 45 if (capacity >= 0) 46 { 47 values = new UnsafeList<int>(capacity, Allocator.Persistent); 48 Random.InitState(0); 49 for (int i = 0; i < capacity; i++) 50 { 51 int randKey = Random.Range(0, capacity); 52 values.Add(randKey); 53 } 54 } 55 else 56 values.Dispose(); 57 } 58 } 59 60 61 struct ArrayLength100k : IBenchmarkContainer 62 { 63 const int kIterations = 100_000; 64 NativeArray<int> nativeContainer; 65 66 public void AllocNativeContainer(int capacity) => ArrayUtil.AllocInt(ref nativeContainer, capacity, true); 67 public void AllocUnsafeContainer(int capacity) { } 68 public object AllocBclContainer(int capacity) => ArrayUtil.AllocBclContainer(capacity, true); 69 70 [MethodImpl(MethodImplOptions.NoOptimization)] 71 public void MeasureNativeContainer() 72 { 73 var reader = nativeContainer.AsReadOnly(); 74 for (int i = 0; i < kIterations; i++) 75 _ = reader.Length; 76 } 77 [MethodImpl(MethodImplOptions.NoOptimization)] 78 public void MeasureUnsafeContainer() { } 79 [MethodImpl(MethodImplOptions.NoOptimization)] 80 public void MeasureBclContainer(object container) 81 { 82 var bclContainer = (int[])container; 83 for (int i = 0; i < kIterations; i++) 84 _ = bclContainer.Length; 85 } 86 } 87 88 struct ArrayIndexedRead : IBenchmarkContainer 89 { 90 NativeArray<int> nativeContainer; 91 UnsafeList<int> values; 92 93 public void AllocNativeContainer(int capacity) 94 { 95 ArrayUtil.AllocInt(ref nativeContainer, capacity, true); 96 ArrayUtil.CreateRandomValues(capacity, ref values); 97 } 98 public void AllocUnsafeContainer(int capacity) { } 99 public object AllocBclContainer(int capacity) 100 { 101 object container = ArrayUtil.AllocBclContainer(capacity, true); 102 ArrayUtil.CreateRandomValues(capacity, ref values); 103 return container; 104 } 105 106 public void MeasureNativeContainer() 107 { 108 var reader = nativeContainer.AsReadOnly(); 109 int insertions = values.Length; 110 int value = 0; 111 for (int i = 0; i < insertions; i++) 112 Volatile.Write(ref value, reader[values[i]]); 113 } 114 public void MeasureUnsafeContainer() { } 115 public void MeasureBclContainer(object container) 116 { 117 var bclContainer = (int[])container; 118 int insertions = values.Length; 119 int value = 0; 120 for (int i = 0; i < insertions; i++) 121 Volatile.Write(ref value, bclContainer[values[i]]); 122 } 123 } 124 125 struct ArrayIndexedWrite : IBenchmarkContainer 126 { 127 NativeArray<int> nativeContainer; 128 UnsafeList<int> values; 129 130 public void AllocNativeContainer(int capacity) 131 { 132 ArrayUtil.AllocInt(ref nativeContainer, capacity, true); 133 ArrayUtil.CreateRandomValues(capacity, ref values); 134 } 135 public void AllocUnsafeContainer(int capacity) { } 136 public object AllocBclContainer(int capacity) 137 { 138 object container = ArrayUtil.AllocBclContainer(capacity, true); 139 ArrayUtil.CreateRandomValues(capacity, ref values); 140 return container; 141 } 142 143 public void MeasureNativeContainer() 144 { 145 int insertions = values.Length; 146 for (int i = 0; i < insertions; i++) 147 nativeContainer[values[i]] = i; 148 } 149 public void MeasureUnsafeContainer() { } 150 public void MeasureBclContainer(object container) 151 { 152 var bclContainer = (int[])container; 153 int insertions = values.Length; 154 for (int i = 0; i < insertions; i++) 155 bclContainer[values[i]] = i; 156 } 157 } 158 159 struct ArrayForEach : IBenchmarkContainer 160 { 161 NativeArray<int> nativeContainer; 162 public int total; 163 164 public void AllocNativeContainer(int capacity) => ArrayUtil.AllocInt(ref nativeContainer, capacity, true); 165 public void AllocUnsafeContainer(int capacity) { } 166 public object AllocBclContainer(int capacity) => ArrayUtil.AllocBclContainer(capacity, true); 167 168 public void MeasureNativeContainer() 169 { 170 int value = 0; 171 foreach (var element in nativeContainer) 172 Volatile.Write(ref value, element); 173 } 174 public void MeasureUnsafeContainer() { } 175 public void MeasureBclContainer(object container) 176 { 177 int value = 0; 178 var bclContainer = (int[])container; 179 foreach (var element in bclContainer) 180 Volatile.Write(ref value, element); 181 } 182 } 183 184 [Benchmark(typeof(BenchmarkContainerType), true)] 185 class Array 186 { 187#if UNITY_EDITOR 188 [UnityEditor.MenuItem(BenchmarkContainerConfig.kMenuItemIndividual + nameof(Array))] 189 static void RunIndividual() 190 => BenchmarkContainerConfig.RunBenchmark(typeof(Array)); 191#endif 192 193 [Test, Performance] 194 [Category("Performance")] 195 public unsafe void Length_x_100k( 196 [Values(0, 100)] int capacity, 197 [Values(BenchmarkContainerType.Native, BenchmarkContainerType.NativeBurstSafety, 198 BenchmarkContainerType.NativeBurstNoSafety)] BenchmarkContainerType type) 199 { 200 BenchmarkContainerRunner<ArrayLength100k>.Run(capacity, type); 201 } 202 203 [Test, Performance] 204 [Category("Performance")] 205 public unsafe void IndexedRead( 206 [Values(10000, 100000, 1000000)] int insertions, 207 [Values(BenchmarkContainerType.Native, BenchmarkContainerType.NativeBurstSafety, 208 BenchmarkContainerType.NativeBurstNoSafety)] BenchmarkContainerType type) 209 { 210 BenchmarkContainerRunner<ArrayIndexedRead>.Run(insertions, type); 211 } 212 213 [Test, Performance] 214 [Category("Performance")] 215 public unsafe void IndexedWrite( 216 [Values(10000, 100000, 1000000)] int insertions, 217 [Values(BenchmarkContainerType.Native, BenchmarkContainerType.NativeBurstSafety, 218 BenchmarkContainerType.NativeBurstNoSafety)] BenchmarkContainerType type) 219 { 220 BenchmarkContainerRunner<ArrayIndexedWrite>.Run(insertions, type); 221 } 222 223 [Test, Performance] 224 [Category("Performance")] 225 public unsafe void Foreach( 226 [Values(10000, 100000, 1000000)] int insertions, 227 [Values(BenchmarkContainerType.Native, BenchmarkContainerType.NativeBurstSafety, 228 BenchmarkContainerType.NativeBurstNoSafety)] BenchmarkContainerType type) 229 { 230 BenchmarkContainerRunner<ArrayForEach>.Run(insertions, type); 231 } 232 } 233}