This is the eleventh part of the Custom memory allocation series. For your convenience you can find other parts in the table of contents in Part 1 — Allocating object on a stack
I presented some results suggesting that UnsafeList
is faster than the array or List< T>
in .NET. Today it’s time to run some more serious benchmark to verify if it is so.
I am running this on Runtime=.NET Framework 4.6.1 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.2671.0 and BenchmarkDotNet=v0.10.14, OS=Windows 10.0.15063.1155 (1703/CreatorsUpdate/Redstone2) Intel Core i5-6300U CPU 2.40GHz (Skylake), 1 CPU, 4 logical and 2 physical cores Frequency=2437502 Hz, Resolution=410.2561 ns, Timer=TSC, as reported by BenchmarkDotNet. The benchmark code is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
using System; using System.Collections.Generic; using System.Collections; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes.Columns; using BenchmarkDotNet.Attributes.Exporters; using BenchmarkDotNet.Attributes.Jobs; using BenchmarkDotNet.Running; using UnsafeListSpace; using UnsafeList_bench; namespace UnsafeListSpace { public class UnsafeList< T> : IEnumerable where T : class { private readonly int _elementSize; private T _target; private int[] _storage; private int _currentIndex = -1; private readonly T[] _elements; public UnsafeList(int size, int elementSize) { _elementSize = elementSize + 1; _storage = new int[size * _elementSize]; _elements = new T[size]; _target = default(T); } public void Add(T item) { _currentIndex++; unsafe { TypedReference reference = __makeref(item); int* itemAddress = (int*)(*(int*)*(int*)&reference - 4); for (int i = 1; i < _elementSize; ++i) { _storage[_currentIndex * _elementSize + i] = *itemAddress; itemAddress = itemAddress + 1; } reference = __makeref(_storage); _storage[_currentIndex * _elementSize] = *(int*)*(int*)&reference + _currentIndex * _elementSize * 4 + 16; _elements[_currentIndex] = GetInternal(_currentIndex); } } private T GetInternal(int index) { unsafe { TypedReference reference = __makeref(_target); *(int*)*(int*)&reference = _storage[index * _elementSize]; T result = __refvalue(reference, T); return result; } } public T Get(int index) { return _elements[index]; } public IEnumerator< T> GetEnumerator() { return new CustomEnumerator< T>(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private class CustomEnumerator< T> : IEnumerator< T> where T : class { private readonly UnsafeList< T> _list; private int _index; private T _current; private int size; public CustomEnumerator(UnsafeList< T> list) { _list = list; _index = -1; size = _list._currentIndex; } public void Dispose() { } public bool MoveNext() { _index++; if (_index < = size) { _current = _list.Get(_index); return true; } return false; } public void Reset() { _index = -1; } public T Current { get { return _current; } } object IEnumerator.Current { get { return _current; } } } } } namespace UnsafeList_bench { public static class Settings { public static int elementsCount = 2 * 1000 * 1000; } public class Poco { public int Field1; public int Field2; public int Field3; public int Field4; public int Field5; public int Field6; public int Field7; public int Field8; public int Field9; public int Field10; public int Field11; public int Field12; public int Field13; public int Field14; public int Field15; public int Field16; public static Poco CreatePoco(int i) { return new Poco { Field1 = i, Field2 = i - 1, Field3 = i - 2, Field4 = i - 3, Field5 = i - 4, Field6 = i - 5, Field7 = i - 6, Field8 = i - 7, Field9 = i - 7, Field10 = i - 6, Field11 = i - 5, Field12 = i - 4, Field13 = i - 3, Field14 = i - 2, Field15 = i - 1, Field16 = i }; } } [ClrJob(isBaseline: true)] [RPlotExporter, RankColumn] public class Insertion { Poco[] array; List< Poco> list; UnsafeList< Poco> unsafeList; [Benchmark] public void ArrayInsertion() { array = new Poco[Settings.elementsCount]; for (int i = 0; i < Settings.elementsCount; ++i) { var poco = Poco.CreatePoco(i); array[i] = poco; } } [Benchmark] public void ListInsertion() { list = new List< Poco>(Settings.elementsCount); for (int i = 0; i < Settings.elementsCount; ++i) { var poco = Poco.CreatePoco(i); list.Add(poco); } } [Benchmark] public void UnsafeInsertion() { unsafeList = new UnsafeList< Poco>(Settings.elementsCount, 18); for (int i = 0; i < Settings.elementsCount; ++i) { var poco = Poco.CreatePoco(i); unsafeList.Add(poco); } } } } namespace UnsafeListBench { public class Program { public static void Main(string[] args) { var insertion = BenchmarkRunner.Run< Insertion>(); } } } |
And here are the results:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 |
// ***** BenchmarkRunner: Start ***** // Found benchmarks: // Insertion.ArrayInsertion: Job-JWVBYN(Runtime=Clr, IsBaseline=True) // Insertion.ListInsertion: Job-JWVBYN(Runtime=Clr, IsBaseline=True) // Insertion.UnsafeInsertion: Job-JWVBYN(Runtime=Clr, IsBaseline=True) // Validating benchmarks: // ***** Building 3 benchmark(s) in Parallel: Start ***** // ***** Done, took 00:00:03 (3.06 sec) ***** // ************************** // Benchmark: Insertion.ArrayInsertion: Job-JWVBYN(Runtime=Clr, IsBaseline=True) // *** Execute *** // Launch: 1 / 1 // Execute: C:\Users\adafurma\Desktop\msp_windowsinternals\UnsafeList_bench\bin\Release\d805cc7b-c85b-4054-ace6-aee8f9b905ee.exe // BeforeAnythingElse // Benchmark Process Environment Information: // Runtime=.NET Framework 4.6.1 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.2671.0 // GC=Concurrent Workstation // Job: Job-JWVBYN(Runtime=Clr, IsBaseline=True) Pilot 1: 16 op, 7154233309.35 ns, 447.1396 ms/op IdleWarmup 1: 16 op, 4923.07 ns, 307.6921 ns/op IdleWarmup 2: 16 op, 820.51 ns, 51.2820 ns/op IdleWarmup 3: 16 op, 820.51 ns, 51.2820 ns/op IdleWarmup 4: 16 op, 820.51 ns, 51.2820 ns/op IdleWarmup 5: 16 op, 820.51 ns, 51.2820 ns/op IdleWarmup 6: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 1: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 2: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 3: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 4: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 5: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 6: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 7: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 8: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 9: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 10: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 11: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 12: 16 op, 1230.77 ns, 76.9230 ns/op IdleTarget 13: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 14: 16 op, 410.26 ns, 25.6410 ns/op IdleTarget 15: 16 op, 820.51 ns, 51.2820 ns/op MainWarmup 1: 16 op, 7348565457.59 ns, 459.2853 ms/op MainWarmup 2: 16 op, 6721045972.48 ns, 420.0654 ms/op MainWarmup 3: 16 op, 6574619015.70 ns, 410.9137 ms/op MainWarmup 4: 16 op, 6977985248.83 ns, 436.1241 ms/op MainWarmup 5: 16 op, 6743144005.63 ns, 421.4465 ms/op MainWarmup 6: 16 op, 7115597853.87 ns, 444.7249 ms/op MainWarmup 7: 16 op, 6551240573.34 ns, 409.4525 ms/op // BeforeMainRun MainTarget 1: 16 op, 6568242405.54 ns, 410.5152 ms/op MainTarget 2: 16 op, 7025800594.21 ns, 439.1125 ms/op MainTarget 3: 16 op, 6979129042.77 ns, 436.1956 ms/op MainTarget 4: 16 op, 6957845367.92 ns, 434.8653 ms/op MainTarget 5: 16 op, 6462374184.72 ns, 403.8984 ms/op MainTarget 6: 16 op, 6577030911.15 ns, 411.0644 ms/op MainTarget 7: 16 op, 6869308414.93 ns, 429.3318 ms/op MainTarget 8: 16 op, 7016557524.88 ns, 438.5348 ms/op MainTarget 9: 16 op, 6861911087.66 ns, 428.8694 ms/op MainTarget 10: 16 op, 6520966136.64 ns, 407.5604 ms/op MainTarget 11: 16 op, 7403562745.79 ns, 462.7227 ms/op MainTarget 12: 16 op, 7025309927.95 ns, 439.0819 ms/op MainTarget 13: 16 op, 7056687132.97 ns, 441.0429 ms/op MainTarget 14: 16 op, 7018985420.32 ns, 438.6866 ms/op MainTarget 15: 16 op, 6581938394.31 ns, 411.3711 ms/op MainTarget 16: 16 op, 6536139457.53 ns, 408.5087 ms/op MainTarget 17: 16 op, 7338629876.00 ns, 458.6644 ms/op MainTarget 18: 16 op, 7956029574.54 ns, 497.2518 ms/op MainTarget 19: 16 op, 7415085608.13 ns, 463.4429 ms/op MainTarget 20: 16 op, 7052814725.90 ns, 440.8009 ms/op MainTarget 21: 16 op, 6651503875.69 ns, 415.7190 ms/op MainTarget 22: 16 op, 7024414338.94 ns, 439.0259 ms/op MainTarget 23: 16 op, 6871126669.84 ns, 429.4454 ms/op MainTarget 24: 16 op, 6580886497.73 ns, 411.3054 ms/op MainTarget 25: 16 op, 6582526291.26 ns, 411.4079 ms/op MainTarget 26: 16 op, 7074069272.56 ns, 442.1293 ms/op MainTarget 27: 16 op, 7400710235.31 ns, 462.5444 ms/op MainTarget 28: 16 op, 6493476518.17 ns, 405.8423 ms/op MainTarget 29: 16 op, 7176358829.65 ns, 448.5224 ms/op MainTarget 30: 16 op, 6491634878.66 ns, 405.7272 ms/op MainTarget 31: 16 op, 7062434410.31 ns, 441.4022 ms/op MainTarget 32: 16 op, 6694712865.88 ns, 418.4196 ms/op MainTarget 33: 16 op, 6929649288.49 ns, 433.1031 ms/op MainTarget 34: 16 op, 7027410439.05 ns, 439.2132 ms/op MainTarget 35: 16 op, 7053880160.92 ns, 440.8675 ms/op MainTarget 36: 16 op, 7336032544.79 ns, 458.5020 ms/op MainTarget 37: 16 op, 7431532774.13 ns, 464.4708 ms/op MainTarget 38: 16 op, 7113560932.46 ns, 444.5976 ms/op MainTarget 39: 16 op, 6931749389.33 ns, 433.2343 ms/op MainTarget 40: 16 op, 6524895569.32 ns, 407.8060 ms/op MainTarget 41: 16 op, 6802759546.45 ns, 425.1725 ms/op MainTarget 42: 16 op, 6874988000.01 ns, 429.6868 ms/op MainTarget 43: 16 op, 6883799890.22 ns, 430.2375 ms/op MainTarget 44: 16 op, 6945833890.60 ns, 434.1146 ms/op MainTarget 45: 16 op, 7085936750.00 ns, 442.8710 ms/op MainTarget 46: 16 op, 6507693121.89 ns, 406.7308 ms/op MainTarget 47: 16 op, 6989439598.41 ns, 436.8400 ms/op MainTarget 48: 16 op, 7018757317.94 ns, 438.6723 ms/op MainTarget 49: 16 op, 6781371666.57 ns, 423.8357 ms/op MainTarget 50: 16 op, 7040904171.57 ns, 440.0565 ms/op // AfterMainRun Result 1: 16 op, 6568241585.03 ns, 410.5151 ms/op Result 2: 16 op, 7025799773.70 ns, 439.1125 ms/op Result 3: 16 op, 6979128222.25 ns, 436.1955 ms/op Result 4: 16 op, 6957844547.41 ns, 434.8653 ms/op Result 5: 16 op, 6462373364.21 ns, 403.8983 ms/op Result 6: 16 op, 6577030090.64 ns, 411.0644 ms/op Result 7: 16 op, 6869307594.41 ns, 429.3317 ms/op Result 8: 16 op, 7016556704.36 ns, 438.5348 ms/op Result 9: 16 op, 6861910267.15 ns, 428.8694 ms/op Result 10: 16 op, 6520965316.13 ns, 407.5603 ms/op Result 11: 16 op, 7403561925.28 ns, 462.7226 ms/op Result 12: 16 op, 7025309107.44 ns, 439.0818 ms/op Result 13: 16 op, 7056686312.46 ns, 441.0429 ms/op Result 14: 16 op, 7018984599.81 ns, 438.6865 ms/op Result 15: 16 op, 6581937573.79 ns, 411.3711 ms/op Result 16: 16 op, 6536138637.01 ns, 408.5087 ms/op Result 17: 16 op, 7338629055.48 ns, 458.6643 ms/op Result 18: 16 op, 7415084787.62 ns, 463.4428 ms/op Result 19: 16 op, 7052813905.38 ns, 440.8009 ms/op Result 20: 16 op, 6651503055.18 ns, 415.7189 ms/op Result 21: 16 op, 7024413518.43 ns, 439.0258 ms/op Result 22: 16 op, 6871125849.33 ns, 429.4454 ms/op Result 23: 16 op, 6580885677.22 ns, 411.3054 ms/op Result 24: 16 op, 6582525470.75 ns, 411.4078 ms/op Result 25: 16 op, 7074068452.05 ns, 442.1293 ms/op Result 26: 16 op, 7400709414.80 ns, 462.5443 ms/op Result 27: 16 op, 6493475697.66 ns, 405.8422 ms/op Result 28: 16 op, 7176358009.14 ns, 448.5224 ms/op Result 29: 16 op, 6491634058.15 ns, 405.7271 ms/op Result 30: 16 op, 7062433589.80 ns, 441.4021 ms/op Result 31: 16 op, 6694712045.36 ns, 418.4195 ms/op Result 32: 16 op, 6929648467.98 ns, 433.1030 ms/op Result 33: 16 op, 7027409618.54 ns, 439.2131 ms/op Result 34: 16 op, 7053879340.41 ns, 440.8675 ms/op Result 35: 16 op, 7336031724.28 ns, 458.5020 ms/op Result 36: 16 op, 7431531953.61 ns, 464.4707 ms/op Result 37: 16 op, 7113560111.95 ns, 444.5975 ms/op Result 38: 16 op, 6931748568.82 ns, 433.2343 ms/op Result 39: 16 op, 6524894748.80 ns, 407.8059 ms/op Result 40: 16 op, 6802758725.94 ns, 425.1724 ms/op Result 41: 16 op, 6874987179.50 ns, 429.6867 ms/op Result 42: 16 op, 6883799069.70 ns, 430.2374 ms/op Result 43: 16 op, 6945833070.09 ns, 434.1146 ms/op Result 44: 16 op, 7085935929.49 ns, 442.8710 ms/op Result 45: 16 op, 6507692301.38 ns, 406.7308 ms/op Result 46: 16 op, 6989438777.90 ns, 436.8399 ms/op Result 47: 16 op, 7018756497.43 ns, 438.6723 ms/op Result 48: 16 op, 6781370846.05 ns, 423.8357 ms/op Result 49: 16 op, 7040903351.05 ns, 440.0565 ms/op GC: 0 0 0 0 0 // AfterAll Mean = 431.9545 ms, StdErr = 2.4464 ms (0.57%); N = 49, StdDev = 17.1251 ms Min = 403.8983 ms, Q1 = 413.5634 ms, Median = 434.8653 ms, Q3 = 440.9552 ms, Max = 464.4707 ms IQR = 27.3918 ms, LowerFence = 372.4757 ms, UpperFence = 482.0429 ms ConfidenceInterval = [423.3796 ms; 440.5294 ms] (CI 99.9%), Margin = 8.5749 ms (1.99% of Mean) Skewness = 0.03, Kurtosis = 2.15, MValue = 2.92 // ************************** // Benchmark: Insertion.ListInsertion: Job-JWVBYN(Runtime=Clr, IsBaseline=True) // *** Execute *** // Launch: 1 / 1 // Execute: C:\Users\adafurma\Desktop\msp_windowsinternals\UnsafeList_bench\bin\Release\ea9fd2e7-c387-4ac9-a241-2c646415e1f9.exe // BeforeAnythingElse // Benchmark Process Environment Information: // Runtime=.NET Framework 4.6.1 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.2671.0 // GC=Concurrent Workstation // Job: Job-JWVBYN(Runtime=Clr, IsBaseline=True) Pilot 1: 16 op, 7325801578.83 ns, 457.8626 ms/op IdleWarmup 1: 16 op, 4923.07 ns, 307.6921 ns/op IdleWarmup 2: 16 op, 820.51 ns, 51.2820 ns/op IdleWarmup 3: 16 op, 820.51 ns, 51.2820 ns/op IdleWarmup 4: 16 op, 410.26 ns, 25.6410 ns/op IdleWarmup 5: 16 op, 820.51 ns, 51.2820 ns/op IdleWarmup 6: 16 op, 1230.77 ns, 76.9230 ns/op IdleWarmup 7: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 1: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 2: 16 op, 410.26 ns, 25.6410 ns/op IdleTarget 3: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 4: 16 op, 410.26 ns, 25.6410 ns/op IdleTarget 5: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 6: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 7: 16 op, 1230.77 ns, 76.9230 ns/op IdleTarget 8: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 9: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 10: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 11: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 12: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 13: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 14: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 15: 16 op, 820.51 ns, 51.2820 ns/op MainWarmup 1: 16 op, 6761338041.98 ns, 422.5836 ms/op MainWarmup 2: 16 op, 6632286660.69 ns, 414.5179 ms/op MainWarmup 3: 16 op, 6703430397.19 ns, 418.9644 ms/op MainWarmup 4: 16 op, 6916518222.34 ns, 432.2824 ms/op MainWarmup 5: 16 op, 6656070436.04 ns, 416.0044 ms/op MainWarmup 6: 16 op, 7126314563.02 ns, 445.3947 ms/op MainWarmup 7: 16 op, 6678495443.29 ns, 417.4060 ms/op // BeforeMainRun MainTarget 1: 16 op, 7399429005.60 ns, 462.4643 ms/op MainTarget 2: 16 op, 6901733824.22 ns, 431.3584 ms/op MainTarget 3: 16 op, 6917735452.11 ns, 432.3585 ms/op MainTarget 4: 16 op, 7076888962.55 ns, 442.3056 ms/op MainTarget 5: 16 op, 6564660459.77 ns, 410.2913 ms/op MainTarget 6: 16 op, 6586053262.73 ns, 411.6283 ms/op MainTarget 7: 16 op, 7234502371.69 ns, 452.1564 ms/op MainTarget 8: 16 op, 6908187972.77 ns, 431.7617 ms/op MainTarget 9: 16 op, 6648146750.24 ns, 415.5092 ms/op MainTarget 10: 16 op, 6808872361.95 ns, 425.5545 ms/op MainTarget 11: 16 op, 6646745315.49 ns, 415.4216 ms/op MainTarget 12: 16 op, 6832064137.79 ns, 427.0040 ms/op MainTarget 13: 16 op, 6618488928.42 ns, 413.6556 ms/op MainTarget 14: 16 op, 6833884443.99 ns, 427.1178 ms/op MainTarget 15: 16 op, 6873002770.87 ns, 429.5627 ms/op MainTarget 16: 16 op, 7127737741.34 ns, 445.4836 ms/op MainTarget 17: 16 op, 7133032506.23 ns, 445.8145 ms/op MainTarget 18: 16 op, 7504547278.32 ns, 469.0342 ms/op MainTarget 19: 16 op, 7143976907.51 ns, 446.4986 ms/op MainTarget 20: 16 op, 6727426685.19 ns, 420.4642 ms/op MainTarget 21: 16 op, 6647545725.09 ns, 415.4716 ms/op MainTarget 22: 16 op, 7070121788.62 ns, 441.8826 ms/op MainTarget 23: 16 op, 7204433883.54 ns, 450.2771 ms/op MainTarget 24: 16 op, 6961947518.40 ns, 435.1217 ms/op MainTarget 25: 16 op, 6876601537.15 ns, 429.7876 ms/op MainTarget 26: 16 op, 6796513807.99 ns, 424.7821 ms/op MainTarget 27: 16 op, 7037623764.00 ns, 439.8515 ms/op MainTarget 28: 16 op, 6720519203.68 ns, 420.0325 ms/op MainTarget 29: 16 op, 6992796723.86 ns, 437.0498 ms/op MainTarget 30: 16 op, 6845292844.89 ns, 427.8308 ms/op MainTarget 31: 16 op, 6802711136.24 ns, 425.1694 ms/op MainTarget 32: 16 op, 7084377776.92 ns, 442.7736 ms/op MainTarget 33: 16 op, 7076028655.57 ns, 442.2518 ms/op MainTarget 34: 16 op, 6895445829.38 ns, 430.9654 ms/op // AfterMainRun Result 1: 16 op, 7399428212.43 ns, 462.4643 ms/op Result 2: 16 op, 6901733031.06 ns, 431.3583 ms/op Result 3: 16 op, 6917734658.95 ns, 432.3584 ms/op Result 4: 16 op, 7076888169.39 ns, 442.3055 ms/op Result 5: 16 op, 6564659666.60 ns, 410.2912 ms/op Result 6: 16 op, 6586052469.56 ns, 411.6283 ms/op Result 7: 16 op, 7234501578.53 ns, 452.1563 ms/op Result 8: 16 op, 6908187179.61 ns, 431.7617 ms/op Result 9: 16 op, 6648145957.08 ns, 415.5091 ms/op Result 10: 16 op, 6808871568.79 ns, 425.5545 ms/op Result 11: 16 op, 6646744522.33 ns, 415.4215 ms/op Result 12: 16 op, 6832063344.63 ns, 427.0040 ms/op Result 13: 16 op, 6618488135.26 ns, 413.6555 ms/op Result 14: 16 op, 6833883650.83 ns, 427.1177 ms/op Result 15: 16 op, 6873001977.71 ns, 429.5626 ms/op Result 16: 16 op, 7127736948.18 ns, 445.4836 ms/op Result 17: 16 op, 7133031713.07 ns, 445.8145 ms/op Result 18: 16 op, 7143976114.34 ns, 446.4985 ms/op Result 19: 16 op, 6727425892.03 ns, 420.4641 ms/op Result 20: 16 op, 6647544931.93 ns, 415.4716 ms/op Result 21: 16 op, 7070120995.46 ns, 441.8826 ms/op Result 22: 16 op, 7204433090.38 ns, 450.2771 ms/op Result 23: 16 op, 6961946725.24 ns, 435.1217 ms/op Result 24: 16 op, 6876600743.99 ns, 429.7875 ms/op Result 25: 16 op, 6796513014.83 ns, 424.7821 ms/op Result 26: 16 op, 7037622970.84 ns, 439.8514 ms/op Result 27: 16 op, 6720518410.51 ns, 420.0324 ms/op Result 28: 16 op, 6992795930.70 ns, 437.0497 ms/op Result 29: 16 op, 6845292051.73 ns, 427.8308 ms/op Result 30: 16 op, 6802710343.08 ns, 425.1694 ms/op Result 31: 16 op, 7084376983.76 ns, 442.7736 ms/op Result 32: 16 op, 7076027862.40 ns, 442.2517 ms/op Result 33: 16 op, 6895445036.22 ns, 430.9653 ms/op GC: 0 0 0 0 0 // AfterAll Mean = 431.8078 ms, StdErr = 2.2424 ms (0.52%); N = 33, StdDev = 12.8817 ms Min = 410.2912 ms, Q1 = 422.6231 ms, Median = 430.9653 ms, Q3 = 442.2786 ms, Max = 462.4643 ms IQR = 19.6555 ms, LowerFence = 393.1398 ms, UpperFence = 471.7619 ms ConfidenceInterval = [423.6862 ms; 439.9294 ms] (CI 99.9%), Margin = 8.1216 ms (1.88% of Mean) Skewness = 0.22, Kurtosis = 2.3, MValue = 2 // ************************** // Benchmark: Insertion.UnsafeInsertion: Job-JWVBYN(Runtime=Clr, IsBaseline=True) // *** Execute *** // Launch: 1 / 1 // Execute: C:\Users\adafurma\Desktop\msp_windowsinternals\UnsafeList_bench\bin\Release\e5bd0317-c5b3-4eb6-b295-ba981cf5385f.exe // BeforeAnythingElse // Benchmark Process Environment Information: // Runtime=.NET Framework 4.6.1 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.2671.0 // GC=Concurrent Workstation // Job: Job-JWVBYN(Runtime=Clr, IsBaseline=True) Pilot 1: 16 op, 3139367270.26 ns, 196.2105 ms/op IdleWarmup 1: 16 op, 22153.83 ns, 1.3846 us/op IdleWarmup 2: 16 op, 820.51 ns, 51.2820 ns/op IdleWarmup 3: 16 op, 410.26 ns, 25.6410 ns/op IdleWarmup 4: 16 op, 820.51 ns, 51.2820 ns/op IdleWarmup 5: 16 op, 410.26 ns, 25.6410 ns/op IdleWarmup 6: 16 op, 820.51 ns, 51.2820 ns/op IdleWarmup 7: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 1: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 2: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 3: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 4: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 5: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 6: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 7: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 8: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 9: 16 op, 410.26 ns, 25.6410 ns/op IdleTarget 10: 16 op, 410.26 ns, 25.6410 ns/op IdleTarget 11: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 12: 16 op, 410.26 ns, 25.6410 ns/op IdleTarget 13: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 14: 16 op, 820.51 ns, 51.2820 ns/op IdleTarget 15: 16 op, 820.51 ns, 51.2820 ns/op MainWarmup 1: 16 op, 3229808221.70 ns, 201.8630 ms/op MainWarmup 2: 16 op, 3250355897.14 ns, 203.1472 ms/op MainWarmup 3: 16 op, 3269364702.06 ns, 204.3353 ms/op MainWarmup 4: 16 op, 3161877610.77 ns, 197.6174 ms/op MainWarmup 5: 16 op, 3118733851.30 ns, 194.9209 ms/op MainWarmup 6: 16 op, 3091931822.00 ns, 193.2457 ms/op MainWarmup 7: 16 op, 3145536701.10 ns, 196.5960 ms/op MainWarmup 8: 16 op, 3076411834.74 ns, 192.2757 ms/op // BeforeMainRun MainTarget 1: 16 op, 3144651778.75 ns, 196.5407 ms/op MainTarget 2: 16 op, 3114337136.95 ns, 194.6461 ms/op MainTarget 3: 16 op, 3148537314.02 ns, 196.7836 ms/op MainTarget 4: 16 op, 3149704082.29 ns, 196.8565 ms/op MainTarget 5: 16 op, 3173224063.00 ns, 198.3265 ms/op MainTarget 6: 16 op, 3106977553.25 ns, 194.1861 ms/op MainTarget 7: 16 op, 3171334833.78 ns, 198.2084 ms/op MainTarget 8: 16 op, 3454962498.49 ns, 215.9352 ms/op MainTarget 9: 16 op, 3117861236.63 ns, 194.8663 ms/op MainTarget 10: 16 op, 3136003580.72 ns, 196.0002 ms/op MainTarget 11: 16 op, 3194968045.15 ns, 199.6855 ms/op MainTarget 12: 16 op, 3150785107.05 ns, 196.9241 ms/op MainTarget 13: 16 op, 3104535709.10 ns, 194.0335 ms/op MainTarget 14: 16 op, 3113840316.85 ns, 194.6150 ms/op MainTarget 15: 16 op, 3145571162.61 ns, 196.5982 ms/op // AfterMainRun Result 1: 16 op, 3144651040.29 ns, 196.5407 ms/op Result 2: 16 op, 3114336398.49 ns, 194.6460 ms/op Result 3: 16 op, 3148536575.56 ns, 196.7835 ms/op Result 4: 16 op, 3149703343.83 ns, 196.8565 ms/op Result 5: 16 op, 3173223324.53 ns, 198.3265 ms/op Result 6: 16 op, 3106976814.79 ns, 194.1861 ms/op Result 7: 16 op, 3171334095.32 ns, 198.2084 ms/op Result 8: 16 op, 3117860498.17 ns, 194.8663 ms/op Result 9: 16 op, 3136002842.25 ns, 196.0002 ms/op Result 10: 16 op, 3194967306.69 ns, 199.6855 ms/op Result 11: 16 op, 3150784368.59 ns, 196.9240 ms/op Result 12: 16 op, 3104534970.64 ns, 194.0334 ms/op Result 13: 16 op, 3113839578.39 ns, 194.6150 ms/op Result 14: 16 op, 3145570424.15 ns, 196.5982 ms/op GC: 0 0 0 0 0 // AfterAll Mean = 196.3050 ms, StdErr = 0.4546 ms (0.23%); N = 14, StdDev = 1.7010 ms Min = 194.0334 ms, Q1 = 194.6460 ms, Median = 196.5694 ms, Q3 = 196.9240 ms, Max = 199.6855 ms IQR = 2.2780 ms, LowerFence = 191.2290 ms, UpperFence = 200.3410 ms ConfidenceInterval = [194.3861 ms; 198.2239 ms] (CI 99.9%), Margin = 1.9189 ms (0.98% of Mean) Skewness = 0.3, Kurtosis = 1.94, MValue = 2 // ***** BenchmarkRunner: Finish ***** // * Export * BenchmarkDotNet.Artifacts\results\Insertion-report.csv BenchmarkDotNet.Artifacts\results\Insertion-report-github.md BenchmarkDotNet.Artifacts\results\Insertion-report.html BenchmarkDotNet.Artifacts\results\Insertion-measurements.csv BuildPlots.R RPlotExporter couldn't find Rscript.exe in your PATH and no R_HOME environment variable is defined // * Detailed results * Insertion.ArrayInsertion: Job-JWVBYN(Runtime=Clr, IsBaseline=True) Runtime = .NET Framework 4.6.1 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.2671.0; GC = Concurrent Workstation Mean = 431.9545 ms, StdErr = 2.4464 ms (0.57%); N = 49, StdDev = 17.1251 ms Min = 403.8983 ms, Q1 = 413.5634 ms, Median = 434.8653 ms, Q3 = 440.9552 ms, Max = 464.4707 ms IQR = 27.3918 ms, LowerFence = 372.4757 ms, UpperFence = 482.0429 ms ConfidenceInterval = [423.3796 ms; 440.5294 ms] (CI 99.9%), Margin = 8.5749 ms (1.99% of Mean) Skewness = 0.03, Kurtosis = 2.15, MValue = 2.92 -------------------- Histogram -------------------- [403.558 ms ; 412.899 ms) | @@@@@@@@@@@@ [412.899 ms ; 422.766 ms) | @@ [422.766 ms ; 432.702 ms) | @@@@@@@ [432.702 ms ; 449.779 ms) | @@@@@@@@@@@@@@@@@@@@@@ [449.779 ms ; 466.101 ms) | @@@@@@ --------------------------------------------------- Insertion.ListInsertion: Job-JWVBYN(Runtime=Clr, IsBaseline=True) Runtime = .NET Framework 4.6.1 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.2671.0; GC = Concurrent Workstation Mean = 431.8078 ms, StdErr = 2.2424 ms (0.52%); N = 33, StdDev = 12.8817 ms Min = 410.2912 ms, Q1 = 422.6231 ms, Median = 430.9653 ms, Q3 = 442.2786 ms, Max = 462.4643 ms IQR = 19.6555 ms, LowerFence = 393.1398 ms, UpperFence = 471.7619 ms ConfidenceInterval = [423.6862 ms; 439.9294 ms] (CI 99.9%), Margin = 8.1216 ms (1.88% of Mean) Skewness = 0.22, Kurtosis = 2.3, MValue = 2 -------------------- Histogram -------------------- [408.771 ms ; 423.989 ms) | @@@@@@@@ [423.989 ms ; 438.743 ms) | @@@@@@@@@@@@@@ [438.743 ms ; 455.729 ms) | @@@@@@@@@@ [455.729 ms ; 465.978 ms) | @ --------------------------------------------------- Insertion.UnsafeInsertion: Job-JWVBYN(Runtime=Clr, IsBaseline=True) Runtime = .NET Framework 4.6.1 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.2671.0; GC = Concurrent Workstation Mean = 196.3050 ms, StdErr = 0.4546 ms (0.23%); N = 14, StdDev = 1.7010 ms Min = 194.0334 ms, Q1 = 194.6460 ms, Median = 196.5694 ms, Q3 = 196.9240 ms, Max = 199.6855 ms IQR = 2.2780 ms, LowerFence = 191.2290 ms, UpperFence = 200.3410 ms ConfidenceInterval = [194.3861 ms; 198.2239 ms] (CI 99.9%), Margin = 1.9189 ms (0.98% of Mean) Skewness = 0.3, Kurtosis = 1.94, MValue = 2 -------------------- Histogram -------------------- [193.416 ms ; 200.303 ms) | @@@@@@@@@@@@@@ --------------------------------------------------- Total time: 00:13:48 (828.75 sec) // * Summary * BenchmarkDotNet=v0.10.14, OS=Windows 10.0.15063.1155 (1703/CreatorsUpdate/Redstone2) Intel Core i5-6300U CPU 2.40GHz (Skylake), 1 CPU, 4 logical and 2 physical cores Frequency=2437502 Hz, Resolution=410.2561 ns, Timer=TSC [Host] : .NET Framework 4.6.1 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.2671.0 Job-JWVBYN : .NET Framework 4.6.1 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.2671.0 Runtime=Clr IsBaseline=True Method | Mean | Error | StdDev | Scaled | Rank | ---------------- |---------:|---------:|----------:|-------:|-----:| ArrayInsertion | 432.0 ms | 8.575 ms | 17.125 ms | 1.00 | 1 | | | | | | | ListInsertion | 431.8 ms | 8.122 ms | 12.882 ms | 1.00 | 1 | | | | | | | UnsafeInsertion | 196.3 ms | 1.919 ms | 1.701 ms | 1.00 | 1 | // * Warnings * MultimodalDistribution Insertion.ArrayInsertion: Runtime=Clr, IsBaseline=True -> It seems that the distribution can have several modes (mValue = 2.92307692307692) // * Hints * Outliers Insertion.ArrayInsertion: Runtime=Clr, IsBaseline=True -> 1 outlier was removed Insertion.ListInsertion: Runtime=Clr, IsBaseline=True -> 1 outlier was removed Insertion.UnsafeInsertion: Runtime=Clr, IsBaseline=True -> 1 outlier was removed // * Legends * Mean : Arithmetic mean of all measurements Error : Half of 99.9% confidence interval StdDev : Standard deviation of all measurements Scaled : Mean(CurrentBenchmark) / Mean(BaselineBenchmark) Rank : Relative position of current benchmark mean among all benchmarks (Arabic style) 1 ms : 1 Millisecond (0.001 sec) // ***** BenchmarkRunner: End ***** // * Artifacts cleanup * |
The most important part is here:
1 2 3 4 5 6 7 |
Method | Mean | Error | StdDev | Scaled | Rank | ---------------- |---------:|---------:|----------:|-------:|-----:| ArrayInsertion | 432.0 ms | 8.575 ms | 17.125 ms | 1.00 | 1 | | | | | | | ListInsertion | 431.8 ms | 8.122 ms | 12.882 ms | 1.00 | 1 | | | | | | | UnsafeInsertion | 196.3 ms | 1.919 ms | 1.701 ms | 1.00 | 1 | |
I used 2 million elements for insertion and as we can see, UnsafeList
is over two times faster.