Example #1
0
        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();
        }
Example #2
0
        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();
        }
Example #3
0
        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();
        }
Example #4
0
        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();
        }
Example #5
0
        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();
        }
Example #6
0
        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();
        }
Example #7
0
        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();
        }
Example #8
0
        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());
        }
Example #10
0
        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();
        }
Example #11
0
        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();
        }
Example #12
0
        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();
        }
Example #13
0
        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();
        }
Example #14
0
        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();
        }
Example #15
0
        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();
        }