public void RentReturnPinnedSlicesRetainablePoolBadBehavior() { // Rent many then return many var maxBuffers = 32; // 2 var buffersToTake = 128; var pool = new RetainableMemoryPool <Byte>(RetainableMemoryPool <Byte> .DefaultFactory); var list = new List <RetainableMemory <byte> >(); using (Benchmark.Run("FullCycle")) { for (int i = 0; i < buffersToTake; i++) { list.Add(pool.RentMemory(64 * 1024)); } for (int i = 0; i < buffersToTake; i++) { list[i].Dispose(); } } Console.WriteLine("Disposing pool"); pool.Dispose(); }
public void RentReturnBenchmarkRetainablePoolOverCapacity() { #if !DEBUG var count = 10_000; #else var count = 1_0; #endif var capacity = 25; var batch = capacity * 2; var pool = new RetainableMemoryPool <Byte>(RetainableMemoryPool <Byte> .DefaultFactory); var list = new List <RetainableMemory <byte> >(batch); using (Benchmark.Run("FullCycle", count * batch)) { for (int i = 0; i < count; i++) { for (int j = 0; j < batch; j++) { list.Add(pool.RentMemory(32 * 1024)); } foreach (var arrayMemory in list) { arrayMemory.Dispose(); } list.Clear(); } } pool.Dispose(); }
public void RentReturnPinnedSlicesRetainablePool() { var maxBuffers = 128 / 64; // 2 var pool = new RetainableMemoryPool <byte>(null, 32 * 1024, 1024 * 1024, maxBuffers, 0); var list = new List <RetainableMemory <byte> >(); using (Benchmark.Run("FullCycle")) { for (int i = 0; i < maxBuffers * 2; i++) { list.Add(pool.RentMemory(64 * 1024)); } for (int i = 0; i < maxBuffers; i++) { ((IDisposable)list[i]).Dispose(); } for (int i = 2; i < maxBuffers * 2; i++) { pool.ReturnInternal(list[i]); } } pool.Dispose(); }
public void RefCountOfPooled() { var pool = new RetainableMemoryPool <Byte>(RetainableMemoryPool <Byte> .DefaultFactory); var buf = (PrivateMemory <byte>)pool.Rent(100); Assert.IsTrue(buf.IsPoolable); Console.WriteLine($"rented: {buf.ReferenceCount}"); buf.Dispose(); Assert.IsTrue(buf.IsDisposed); Assert.IsTrue(buf.IsPooled); Console.WriteLine($"returned: {buf.ReferenceCount}"); Console.WriteLine($"pooled: {buf.IsPooled}"); Assert.Throws <ObjectDisposedException>(() => { var _ = buf.Retain(); }); pool.Dispose(); }
public void RefCountOfPooled() { var pool = new RetainableMemoryPool <byte>(null, 16, 1024 * 1024, 50, 2); var buf = (ArrayMemory <byte>)pool.Rent(100); Assert.IsTrue(buf.IsPoolable); Console.WriteLine($"rented: {buf.ReferenceCount}"); pool.ReturnInternal(buf); Assert.IsTrue(buf.IsDisposed); Assert.IsTrue(buf.IsPooled); Console.WriteLine($"returned: {buf.ReferenceCount}"); Console.WriteLine($"pooled: {buf.IsPooled}"); Assert.Throws <ObjectDisposedException>(() => { var _ = buf.Retain(); }); pool.Dispose(); }
public void RentReturnBenchmarkRetainablePoolOverCapacity() { var count = 1_000_000; var capacity = 25; var batch = capacity * 2; var pool = new RetainableMemoryPool <byte>((p, l) => { var am = ArrayMemory <byte> .Create(l, pin: true); // Attach pool am._pool = p; return(am); }, 16, 1024 * 1024, capacity, 0); var list = new List <RetainableMemory <byte> >(batch); using (Benchmark.Run("FullCycle", count * batch)) { for (int i = 0; i < count; i++) { for (int j = 0; j < batch; j++) { list.Add(pool.RentMemory(32 * 1024)); } foreach (var arrayMemory in list) { pool.Return(arrayMemory); } list.Clear(); } } pool.Dispose(); }
public void ConcurrentRentReturn() { #if !DEBUG var count = 100_000_000; #else var count = 1_000; #endif var pool = new RetainableMemoryPool <byte>(null, 16, 1024 * 1024, 50, 2); var tasks = new List <Task>(); var taskCount = 1; // 6x2 cores var mre = new ManualResetEventSlim(false); Action action = () => { mre.Wait(); for (int i = 0; i < count; i++) { // ReSharper disable once AccessToDisposedClosure var memory = pool.RentMemory(32 * 1024); //(memory.Pin(0)).Dispose(); //if (memory.IsDisposed || memory.IsRetained) //{ // Assert.Fail(); //} // ReSharper disable once AccessToDisposedClosure pool.ReturnInternal(memory); //if (i % 1000000 == 0) //{ // Console.WriteLine(i); //} } }; for (int i = 0; i < taskCount; i++) { tasks.Add(Task.Run(action)); } //Console.WriteLine("Set affinity and press enter"); //Console.ReadLine(); using (Benchmark.Run("FullCycle", count * taskCount)) { mre.Set(); Task.WhenAll(tasks).Wait(); } pool.Dispose(); }
public void PoolReturnsSameSizeUsingSlices(int maxBucketsToTry) { var pool = new RetainableMemoryPool <byte>(null, 16, 8 * 1024 * 1024, maxBuffersPerBucketPerCore: 8, maxBucketsToTry); var cw = new ConditionalWeakTable <byte[], object>(); var list = new List <ArrayMemory <byte> >(); ArraySegment <byte> prev = default; for (int r = 0; r < TestUtils.GetBenchCount(50, 5); r++) { for (int i = 0; i < TestUtils.GetBenchCount(10240, 1024); i++) { const int sizeKb = 1; var buf = (ArrayMemory <byte>)pool.Rent(sizeKb * 1024); list.Add(buf); if (!cw.TryGetValue(buf.Array, out var id)) { id = (object)i; cw.Add(buf.Array, id); } Assert.IsFalse(buf.ArraySegment.Array == prev.Array && buf.ArraySegment.Offset == prev.Offset, $"different segments at {i}"); prev = buf.ArraySegment; Assert.AreEqual(sizeKb * 1024, buf.Length, $"at {i}"); //Console.Write( // $"{i}: {(int) id} - {buf.Array.Length} - {buf.ArraySegment.Offset} - {buf.ArraySegment.Count}"); //Console.WriteLine(); //if (i > 8 && i <= 23) //{ // Assert.AreEqual(sizeKb * 2 * 1024, buf.Array.Length, $"at {i}"); // Assert.AreEqual((i & 1) * sizeKb * 1024, buf.ArraySegment.Offset, $"at {i}"); //} } foreach (var buf in list) { buf.Dispose(); //pool.Return(buf); } list.Clear(); } pool.Dispose(); }
internal void RmpBenchmark <T>(RetainableMemoryPool <T> pool, string testCase) { var prevRent = BuffersStatistics.RentReturnedBeforeYield.Value; var prevReturn = BuffersStatistics.ReturnReturnedBeforeYield.Value; var prevSCRent = BuffersStatistics.SameCoreRentContention.Value; var prevSCReturn = BuffersStatistics.SameCoreReturnContention.Value; var prevRentLoop = BuffersStatistics.RentLoop.Value; var prevReturnLoop = BuffersStatistics.ReturnLoop.Value; var count = TestUtils.GetBenchCount(10_000_000, 1000_000); var threadCount = Environment.ProcessorCount; using (Benchmark.Run(testCase, count * 2 * threadCount)) { Task.WaitAll(Enumerable.Range(0, threadCount).Select(_ => Task.Factory.StartNew(() => { var size = 8 * 1024; var x0 = pool.RentMemory(size); try { for (int i = 0; i < count; i++) { var x1 = pool.RentMemory(size); var x2 = pool.RentMemory(size); // if(x1 == x2) // ThrowHelper.FailFast("WTF!"); x1.Dispose(); x2.Dispose(); } } catch (Exception ex) { Console.WriteLine($"EXCEPTION: {ex}"); } x0.Dispose(); }, TaskCreationOptions.LongRunning)).ToArray()); } // Console.WriteLine( // $"Rent: {BuffersStatistics.RentReturnedBeforeYield.Value - prevRent:N0} Return: {BuffersStatistics.ReturnReturnedBeforeYield.Value - prevReturn:N0} " + // $"SCRent: {BuffersStatistics.SameCoreRentContention.Value - prevSCRent:N0} SCReturn: {BuffersStatistics.SameCoreReturnContention.Value - prevSCReturn:N0}" + // $"RentLoop: {BuffersStatistics.RentLoop.Value - prevRentLoop:N0} ReturnLoop: {BuffersStatistics.ReturnLoop.Value - prevReturnLoop:N0}"); // Console.WriteLine(pool.InspectObjects().Count()); }
public void CouldDisposePoolWithFreeSpace() { var maxBuffers = 10; var pool = new RetainableMemoryPool <Byte>(RetainableMemoryPool <Byte> .DefaultFactory); using (Benchmark.Run("FullCycle")) { for (int i = 0; i < maxBuffers / 2; i++) { var memory = pool.RentMemory(64 * 1024); memory.Dispose(); // pool.ReturnInternal(memory); } } pool.Dispose(); }
public void CouldDisposePoolWithFreeSpace() { var maxBuffers = 10; var pool = new RetainableMemoryPool <byte>(null, 32 * 1024, 1024 * 1024, maxBuffers, 0); using (Benchmark.Run("FullCycle")) { for (int i = 0; i < maxBuffers / 2; i++) { var memory = pool.RentMemory(64 * 1024); pool.ReturnInternal(memory); } } pool.Dispose(); }
public void RentReturnPinnedSlicesRetainablePoolBadBehaviorDropped() { // Rent many then return many var maxBuffers = 32; // 2 #if !DEBUG var buffersToTake = 1_00_000; #else var buffersToTake = 1_000; #endif var pool = new RetainableMemoryPool <byte>(null, 32 * 1024, 1024 * 1024, maxBuffers, 0); using (Benchmark.Run("FullCycle", buffersToTake)) { for (int i = 0; i < buffersToTake; i++) { // ReSharper disable once UnusedVariable var memory = pool.RentMemory(64 * 1024); // pool.Return(memory); //if (i % 100_000 == 0) //{ // Console.WriteLine(i); //} if (i % 1000 == 0) { GC.Collect(2, GCCollectionMode.Forced, true); GC.WaitForPendingFinalizers(); GC.Collect(2, GCCollectionMode.Forced, true); GC.WaitForPendingFinalizers(); } } GC.Collect(2, GCCollectionMode.Forced, true); GC.WaitForPendingFinalizers(); GC.Collect(2, GCCollectionMode.Forced, true); GC.WaitForPendingFinalizers(); } Console.WriteLine("Disposing pool"); pool.Dispose(); }
public void RentReturnDefaultRetainablePoolBench() { #if !DEBUG var count = 10_000_000; #else var count = 1_000; #endif var pool = new RetainableMemoryPool <byte>(null, 16, 1024 * 1024, 50, 2); for (int i = 0; i < 1000; i++) { var memory = pool.RentMemory(32 * 1024); memory.Increment(); memory.Decrement(); // ((IDisposable)memory).Dispose(); //(memory.Pin(0)).Dispose(); //if (memory.IsDisposed || memory.IsRetained) //{ // Assert.Fail(); //} // pool.Return(memory); } for (int _ = 0; _ < 20; _++) { using (Benchmark.Run("RentReturn", count)) { for (int i = 0; i < count; i++) { var memory = pool.RentMemory(32 * 1024); //(memory.Pin(0)).Dispose(); //if (memory.IsDisposed || memory.IsRetained) //{ // Assert.Fail(); //} pool.Return(memory, false); } } } Benchmark.Dump(); pool.Dispose(); }
public void RentReturnDefaultRetainablePoolBench() { var count = TestUtils.GetBenchCount(1_000_000, 1_000); var pool = new RetainableMemoryPool <byte>(null, 16, 1024 * 1024, 50, 2); for (int i = 0; i < 1000; i++) { var memory = pool.RentMemory(32 * 1024); memory.Increment(); memory.Decrement(); // memory.Dispose(); //(memory.Pin(0)).Dispose(); //if (memory.IsDisposed || memory.IsRetained) //{ // Assert.Fail(); //} // pool.Return(memory); } for (int _ = 0; _ < 20; _++) { using (Benchmark.Run("RentReturn", count)) { for (int i = 0; i < count; i++) { var memory = pool.RentMemory(32 * 1024); //(memory.Pin(0)).Dispose(); //if (memory.IsDisposed || memory.IsRetained) //{ // Assert.Fail(); //} memory.Dispose(); } } } Benchmark.Dump(); pool.Dispose(); }
public void RentReturnBenchmarkRetainablePool() { var count = 100_000_000; var pool = new RetainableMemoryPool <byte>(null, 16, 1024 * 1024, 50, 2); for (int i = 0; i < 1000; i++) { var memory = pool.RentMemory(32 * 1024); memory.Increment(); memory.Decrement(); // ((IDisposable)memory).Dispose(); //(memory.Pin(0)).Dispose(); //if (memory.IsDisposed || memory.IsRetained) //{ // Assert.Fail(); //} // pool.Return(memory); } using (Benchmark.Run("FullCycle", count)) { for (int i = 0; i < count; i++) { var memory = pool.RentMemory(32 * 1024); //(memory.Pin(0)).Dispose(); //if (memory.IsDisposed || memory.IsRetained) //{ // Assert.Fail(); //} pool.Return(memory); } } pool.Dispose(); }