/// <summary> /// Creates a new memory pool. /// </summary> /// <param name="memoryPoolSize">Size of the pool in elements.</param> public Allocator(long memoryPoolSize, int allocationCountEstimate = 128) { this.Capacity = memoryPoolSize; QuickDictionary <ulong, Allocation, Array <ulong>, Array <Allocation>, Array <int>, PrimitiveComparer <ulong> > .Create( new PassthroughArrayPool <ulong>(), new PassthroughArrayPool <Allocation>(), new PassthroughArrayPool <int>(), SpanHelper.GetContainingPowerOf2(allocationCountEstimate), 3, out allocations); }
public SimulationProfiler(int initialStageCount = 8) { QuickDictionary <object, double, Array <object>, Array <double>, Array <int>, ReferenceComparer <object> > .Create( objectPool, doublePool, intPool, SpanHelper.GetContainingPowerOf2(initialStageCount), 3, out stages); QuickDictionary <object, long, Array <object>, Array <long>, Array <int>, ReferenceComparer <object> > .Create( objectPool, longPool, intPool, SpanHelper.GetContainingPowerOf2(initialStageCount), 3, out startTimeStamps); }
public static void TestDictionaryResizing <TSpan, TPool>(TPool pool) where TSpan : ISpan <int> where TPool : IMemoryPool <int, TSpan> { Random random = new Random(5); QuickDictionary <int, int, TSpan, TSpan, TSpan, PrimitiveComparer <int> > .Create(pool, pool, pool, 2, 3, out var dictionary); Dictionary <int, int> controlDictionary = new Dictionary <int, int>(); for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex) { if (random.NextDouble() < 0.7) { dictionary.Add(iterationIndex, iterationIndex, pool, pool, pool); controlDictionary.Add(iterationIndex, iterationIndex); } if (random.NextDouble() < 0.2) { var indexToRemove = random.Next(dictionary.Count); var toRemove = dictionary.Keys[indexToRemove]; dictionary.FastRemove(toRemove); controlDictionary.Remove(toRemove); } if (iterationIndex % 1000 == 0) { dictionary.EnsureCapacity(dictionary.Count * 3, pool, pool, pool); } else if (iterationIndex % 7777 == 0) { dictionary.Compact(pool, pool, pool); } } Debug.Assert(dictionary.Count == controlDictionary.Count); for (int i = 0; i < dictionary.Count; ++i) { Debug.Assert(controlDictionary.ContainsKey(dictionary.Keys[i])); } foreach (var element in controlDictionary.Keys) { Debug.Assert(dictionary.ContainsKey(element)); } dictionary.Dispose(pool, pool, pool); }
public unsafe void Render(DeviceContext context, Camera camera, Int2 screenResolution, MeshInstance[] instances, int start, int count) { //Examine the set of instances and batch them into groups using the same mesh data. var keyPool = meshCache.Pool.SpecializeFor <ulong>(); var valuePool = meshCache.Pool.SpecializeFor <QuickList <MeshInstance, Buffer <MeshInstance> > >(); var tablePool = meshCache.Pool.SpecializeFor <int>(); var instancePool = meshCache.Pool.SpecializeFor <MeshInstance>(); //(but is this ENOUGH generics?) QuickDictionary < ulong, QuickList <MeshInstance, Buffer <MeshInstance> >, Buffer <ulong>, Buffer <QuickList <MeshInstance, Buffer <MeshInstance> > >, Buffer <int>, PrimitiveComparer <ulong> > .Create(keyPool, valuePool, tablePool, 4, 3, out var batches); var end = start + count; for (int i = start; i < end; ++i) { ref var instance = ref instances[i]; ref var id = ref Unsafe.As <int, ulong>(ref instance.VertexStart);
public static void Test() { //var random = new Random(5); //var comparer = new CollidablePairComparer(); //for (int i = 0; i < 10000; ++i) //{ // var a = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // var b = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // var pair1 = new CollidablePair(a, b); // var pair2 = new CollidablePair(b, a); // Debug.Assert(comparer.Hash(ref pair1) == comparer.Hash(ref pair2)); // Debug.Assert(comparer.Equals(ref pair1, ref pair2)); //} //for (int i = 0; i < 10000; ++i) //{ // var a = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // var b = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // var pair1 = new CollidablePair(a, b); // CollidablePair pair2; // do // { // var a2 = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // var b2 = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // pair2 = new CollidablePair(a2, b2); // } while ( // (pair2.A.Packed == pair1.A.Packed && pair2.B.Packed == pair1.B.Packed) || // (pair2.B.Packed == pair1.A.Packed && pair2.A.Packed == pair1.B.Packed)); // Debug.Assert(!comparer.Equals(ref pair1, ref pair2)); //} const int iterationCount = 1000; const int perLayerCollidableCount = 900; const int layerCount = 10; int[] creationRemap = new int[perLayerCollidableCount * (layerCount - 1)]; int[] lookupRemap = new int[creationRemap.Length]; for (int i = 0; i < creationRemap.Length; ++i) { creationRemap[i] = i; lookupRemap[i] = i; } QuickDictionary <CollidablePair, int, Array <CollidablePair>, Array <int>, Array <int>, CollidablePairComparer> .Create( new PassthroughArrayPool <CollidablePair>(), new PassthroughArrayPool <int>(), new PassthroughArrayPool <int>(), SpanHelper.GetContainingPowerOf2(creationRemap.Length), 1, out var dictionary); var random = new Random(5); for (int i = 0; i < creationRemap.Length - 1; ++i) { { var temp = creationRemap[i]; var swapTarget = random.Next(i + 1, creationRemap.Length); creationRemap[i] = creationRemap[swapTarget]; creationRemap[swapTarget] = temp; } { var temp = lookupRemap[i]; var swapTarget = random.Next(i + 1, lookupRemap.Length); lookupRemap[i] = lookupRemap[swapTarget]; lookupRemap[swapTarget] = temp; } } int accumulator = 0; double totalTime = 0; const int warmupIterations = 128; for (int iterationIndex = 0; iterationIndex < iterationCount + warmupIterations; ++iterationIndex) { dictionary.Clear(); for (int i = 0; i < creationRemap.Length; ++i) { var index = creationRemap[i]; var pair = new CollidablePair { A = new CollidableReference(CollidableMobility.Kinematic, index), B = new CollidableReference(CollidableMobility.Dynamic, index + perLayerCollidableCount) }; dictionary.AddUnsafely(ref pair, ref index); } CacheBlaster.Blast(); //Prewarm the remap into cache to more closely mirror the behavior in the narrow phase. for (int i = 0; i < lookupRemap.Length; ++i) { accumulator += lookupRemap[i]; } var start = Stopwatch.GetTimestamp(); for (int i = 0; i < lookupRemap.Length; ++i) { var collidableIndex = lookupRemap[i]; var pair = new CollidablePair { A = new CollidableReference(CollidableMobility.Kinematic, collidableIndex), B = new CollidableReference(CollidableMobility.Dynamic, collidableIndex + perLayerCollidableCount) }; var dictionaryIndex = dictionary.IndexOf(ref pair); accumulator += dictionaryIndex; } var end = Stopwatch.GetTimestamp(); if (iterationIndex >= warmupIterations) { totalTime += (end - start) / (double)Stopwatch.Frequency; } } Console.WriteLine($"Time per lookup (ns): {1e9 * totalTime / (iterationCount * creationRemap.Length)}, acc{accumulator}"); }