public void SingleThreadAccessTest(int size, bool prefill) { ConcurrentRingBufferImpl <Data> pool = new ConcurrentRingBufferImpl <Data>(size); pool.Initialize(() => new Data(), prefill); var distintValues = pool.Data.Distinct(new DataComparer()).Count(); Assert.Equal(pool.Data.Count, distintValues); List <Data> list = new List <Data>(size); for (int x = 0; x < size; x++) { var item = pool.Pop(); item.Counter += 1; list.Add(item); } Assert.Equal(0, pool.Data.Count); for (int x = 0; x < size; x++) { pool.Push(list[x]); } foreach (var item in pool.Data) { item.tracked = false; } GC.Collect(2, GCCollectionMode.Forced); long totalUsage = 0; long totalCount = 0; foreach (var item in pool.Data) { if (item.Counter > 0) { totalUsage += 1; } totalCount += item.Counter; } Console.WriteLine("Counter:" + totalCount); Console.WriteLine("Usage:" + totalUsage); Console.WriteLine("Thrown away:" + Data.destroyed); distintValues = pool.Data.Distinct(new DataComparer()).Count(); Assert.True(pool.Data.Count <= distintValues); Assert.True(size <= pool.Data.Count); }
public void TestEnumeration() { int size = 4; ConcurrentRingBufferImpl <Data> list = new ConcurrentRingBufferImpl <Data>(size); list.Initialize(() => new Data(), true); int count = 0; foreach (var item in list) { count += 1; Console.WriteLine(item.Hash); } Assert.Equal(size, count); }
public void ShouldNotBeAbleToPopFromAnEmptyBuffer(int size) { var evt = new ManualResetEvent(false); Thread t = new Thread(() => { var buffer = new ConcurrentRingBufferImpl <Data>(size); buffer.Initialize(() => new Data(), false); var data = buffer.Pop(); Assert.NotNull(data); }); t.Start(); if (evt.WaitOne(100)) { Assert.False(true, "Thread managed to pop from an empty buffer"); } }
public void TestSimplePopPush() { var pool1 = new ConcurrentRingBufferImpl <Data>(4); var pool2 = new ConcurrentRingBufferImpl <Data>(4); pool1.Initialize(() => new Data(), true); pool2.Initialize(() => new Data(), true); var quitEvent = new ManualResetEvent(false); var t1 = new Thread(() => { do { var item = pool1.Pop(); Thread.Sleep(TimeSpan.FromTicks(new Random(Thread.CurrentThread.ManagedThreadId).Next(5))); pool2.Push(item); }while (!quitEvent.WaitOne(1, true)); }); var t2 = new Thread(() => { do { var item = pool2.Pop(); Thread.Sleep(TimeSpan.FromTicks(new Random(Thread.CurrentThread.ManagedThreadId).Next(5))); pool1.Push(item); }while (!quitEvent.WaitOne(1, true)); }); t1.Start(); t2.Start(); Thread.Sleep(50); quitEvent.Set(); t1.Join(); t2.Join(); GC.Collect(2, GCCollectionMode.Forced); Console.WriteLine("Created:{0}", Data.numberCreated); Console.WriteLine("Thrown away:{0}", Data.destroyed); }
public void ShouldBeAbleToEmptyBufferCompletely(int size) { var buffer = new ConcurrentRingBufferImpl <Data>(size); buffer.Initialize(() => new Data(), false); List <Data> list = new List <Data>(); for (int x = 0; x < size; x++) { var data = new Data(); list.Add(data); buffer.Push(data); } for (int x = 0; x < size; x++) { Assert.True(list.Contains(buffer.Pop())); } }
public void ShouldNotBeAbleToAddMoreToAFullBuffer(int size) { var evt = new ManualResetEvent(false); Thread t = new Thread(() => { var buffer = new ConcurrentRingBufferImpl <Data>(size); buffer.Initialize(() => new Data(), false); for (int x = 0; x < size; x++) { buffer.Push(new Data()); } buffer.Push(new Data()); }); t.Start(); if (evt.WaitOne(100)) { Assert.False(true, "Thread managed to push more than there is room for"); } }
public void PerformanceComparison() { int count = 120000; int iterations = 10000; int threadCount = 2; var cPool = new ConcurrentRingBufferImpl <Data>(count); cPool.Initialize(() => new Data(), true); var stack = new Stack <Data>(count); for (int x = 0; x < count; x++) { stack.Push(new Data()); } var wrapper = new StackWrapper <Data>(stack); Action action = () => { this.StackRunner(iterations, wrapper); //this.StackRunner2(iterations, wrapper2); //this.PoolRunner(iterations, cPool); }; TimeSpan begin = TimeSpan.Zero; DateTime now = DateTime.Now; while (true) { begin += RunPerformanceTest(action, threadCount); GC.Collect(2, GCCollectionMode.Forced); if ((DateTime.Now - now) > TimeSpan.FromSeconds(10)) { break; } } Console.WriteLine((DateTime.Now - now)); int totalCount = 0; int totalUsage = 0; foreach (var item in stack) { if (item.Counter > 0) { totalUsage += 1; } totalCount += item.Counter; } foreach (var item in cPool.Data) { if (item.Counter > 0) { totalUsage += 1; } totalCount += item.Counter; } Console.WriteLine("Counter:" + totalCount); Console.WriteLine("Usage:" + totalUsage); Console.WriteLine("Thrown away (pool):" + cPool.ThrownAwayObjects); Console.WriteLine("Created (pool):" + cPool.Created); }
public void MultiThreadedAccess(int size, bool prefill, int threadCount, int sleep) { ConcurrentRingBufferImpl <Data> pool = new ConcurrentRingBufferImpl <Data>(size); pool.Initialize(() => new Data(), prefill); var distintValues = pool.Data.Distinct(new DataComparer()).Count(); Assert.Equal(pool.Data.Count, distintValues); int localCount = Math.Max(1, size / threadCount); List <Thread> threads = new List <Thread>(); ManualResetEvent startEvent = new ManualResetEvent(false); StringBuilder sb = new StringBuilder(); Console.WriteLine("Testing with:{0} items per thread", localCount); for (int y = 0; y < threadCount; y++) { var thread = new Thread(() => { var random = new Random(Thread.CurrentThread.ManagedThreadId); try { startEvent.WaitOne(); Thread.Sleep(TimeSpan.FromTicks(random.Next(5))); Stack <Data> list = new Stack <Data>(localCount); for (int x = 0; x < localCount; x++) { var item = pool.Pop(); item.SetOwner(); Thread.Sleep(TimeSpan.FromMilliseconds(random.Next(2) * sleep)); item.Counter += 1; list.Push(item); } // Assert that we got at least as many as we requested Assert.Equal(localCount, list.Count); for (int x = localCount - 1; x > -1; x--) { var item = list.Pop(); Thread.Sleep(TimeSpan.FromMilliseconds(random.Next(1))); item.ReleaseOwner(); pool.Push(item); } } catch (Exception e) { lock (sb) { sb.Append(e); } } }); threads.Add(thread); } threads.ForEach(t => t.Start()); startEvent.Set(); Parallel.ForEach(threads, t => t.Join(TimeSpan.FromSeconds(10))); if (sb.Length > 0) { Assert.True(false, sb.ToString()); } foreach (var item in pool.Data) { item.tracked = false; } GC.Collect(2, GCCollectionMode.Forced); long totalUsage = 0; long totalCount = 0; foreach (var item in pool.Data) { if (item.Counter > 0) { totalUsage += 1; } totalCount += item.Counter; } Console.WriteLine("Counter:" + totalCount); Console.WriteLine("Usage:" + totalUsage); Console.WriteLine("Thrown away:" + Data.destroyed); Console.WriteLine("Thrown away (pool):" + pool.ThrownAwayObjects); Console.WriteLine("Created (pool):" + pool.Created); distintValues = pool.Data.Distinct(new DataComparer()).Count(); Assert.True(pool.Data.Count <= distintValues); if (prefill) { // We cant know how many objects are created when we dont prefill pools if (threadCount <= size) { Assert.Equal(size, pool.ObjectsInPool); } } }