public void TestWeakConcurrentDictionaryReferencesObservable() { const int elements = 100000; Random random = new Random(); WeakConcurrentDictionary<int, ObservableTestClass> weakConcurrentDictionary = new WeakConcurrentDictionary<int, ObservableTestClass>(allowResurrection: false); ConcurrentDictionary<int, ObservableTestClass> referenceDictionary = new ConcurrentDictionary<int, ObservableTestClass>(); int nullCount = 0; int unreferencedNullCount = 0; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); Parallel.For( 0, elements, l => { // Include nulls ~25% of the time. ObservableTestClass t; if (random.Next(4) < 3) t = new ObservableTestClass(random.Next(int.MinValue, int.MaxValue)); else { t = null; Interlocked.Increment(ref nullCount); } weakConcurrentDictionary.Add(l, t); // Only keep references ~33% of the time. if (random.Next(3) == 0) referenceDictionary.AddOrUpdate(l, t, (k, v) => t); else if (t == null) Interlocked.Increment(ref unreferencedNullCount); }); stopwatch.Stop(); Trace.WriteLine(stopwatch.ToString("Populating dictionaries with {0} elements", elements)); //GC.WaitForFullGCComplete(5000); stopwatch.Restart(); long bytes = GC.GetTotalMemory(true); stopwatch.Stop(); Trace.WriteLine(stopwatch.ToString("Garbage collection")); Trace.WriteLine(string.Format("Memory: {0}K", bytes / 1024)); // Check that we have l Assert.IsTrue(referenceDictionary.Count <= elements); int refCount = referenceDictionary.Count; stopwatch.Restart(); int weakCount = weakConcurrentDictionary.Count; stopwatch.Stop(); Trace.WriteLine(stopwatch.ToString("Counting '{0}' elements", weakCount)); stopwatch.Restart(); weakCount = weakConcurrentDictionary.Count; stopwatch.Stop(); Trace.WriteLine(stopwatch.ToString("Counting '{0}' elements again", weakCount)); int floor = refCount + unreferencedNullCount; Trace.WriteLine( string.Format( "Referenced Dictionary Count: {1}{0}Weak Dictionary Count: {2}{0}Null values: {3} (unreferenced: {4}){0}Garbage Collected: {5}{0}Pending Collection: {6}{0}", Environment.NewLine, refCount, weakCount, nullCount, unreferencedNullCount, elements - weakCount, weakCount - floor )); // Check we only have references to referenced elements. Assert.AreEqual(refCount + unreferencedNullCount, weakCount); // Check everything that's still referenced is available. stopwatch.Restart(); Parallel.ForEach( referenceDictionary, kvp => { ObservableTestClass value; Assert.IsTrue(weakConcurrentDictionary.TryGetValue(kvp.Key, out value)); Assert.AreEqual(kvp.Value, value); }); stopwatch.Stop(); Trace.WriteLine(stopwatch.ToString("Checking '{0}' elements", weakCount)); }
public void TestWeakConcurrentDictionaryReferencesObservable() { const int elements = 100000; Random random = new Random(); WeakConcurrentDictionary <int, ObservableTestClass> weakConcurrentDictionary = new WeakConcurrentDictionary <int, ObservableTestClass>(allowResurrection: false); ConcurrentDictionary <int, ObservableTestClass> referenceDictionary = new ConcurrentDictionary <int, ObservableTestClass>(); int nullCount = 0; int unreferencedNullCount = 0; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); Parallel.For( 0, elements, l => { // Include nulls ~25% of the time. ObservableTestClass t; if (random.Next(4) < 3) { t = new ObservableTestClass(random.Next(int.MinValue, int.MaxValue)); } else { t = null; Interlocked.Increment(ref nullCount); } weakConcurrentDictionary.Add(l, t); // Only keep references ~33% of the time. if (random.Next(3) == 0) { referenceDictionary.AddOrUpdate(l, t, (k, v) => t); } else if (t == null) { Interlocked.Increment(ref unreferencedNullCount); } }); stopwatch.Stop(); Trace.WriteLine(stopwatch.ToString("Populating dictionaries with {0} elements", elements)); //GC.WaitForFullGCComplete(5000); stopwatch.Restart(); long bytes = GC.GetTotalMemory(true); stopwatch.Stop(); Trace.WriteLine(stopwatch.ToString("Garbage collection")); Trace.WriteLine(string.Format("Memory: {0}K", bytes / 1024)); // Check that we have l Assert.IsTrue(referenceDictionary.Count <= elements); int refCount = referenceDictionary.Count; stopwatch.Restart(); int weakCount = weakConcurrentDictionary.Count; stopwatch.Stop(); Trace.WriteLine(stopwatch.ToString("Counting '{0}' elements", weakCount)); stopwatch.Restart(); weakCount = weakConcurrentDictionary.Count; stopwatch.Stop(); Trace.WriteLine(stopwatch.ToString("Counting '{0}' elements again", weakCount)); int floor = refCount + unreferencedNullCount; Trace.WriteLine( string.Format( "Referenced Dictionary Count: {1}{0}Weak Dictionary Count: {2}{0}Null values: {3} (unreferenced: {4}){0}Garbage Collected: {5}{0}Pending Collection: {6}{0}", Environment.NewLine, refCount, weakCount, nullCount, unreferencedNullCount, elements - weakCount, weakCount - floor )); // Check we only have references to referenced elements. Assert.AreEqual(refCount + unreferencedNullCount, weakCount); // Check everything that's still referenced is available. stopwatch.Restart(); Parallel.ForEach( referenceDictionary, kvp => { ObservableTestClass value; Assert.IsTrue(weakConcurrentDictionary.TryGetValue(kvp.Key, out value)); Assert.AreEqual(kvp.Value, value); }); stopwatch.Stop(); Trace.WriteLine(stopwatch.ToString("Checking '{0}' elements", weakCount)); }