using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Linq; class Program { struct testedge : IEquatable<testedge> { readonly public int a; readonly public int b; public testedge(Random rnd) { a = rnd.Next(); b = rnd.Next(); } public override int GetHashCode() { return a ^ b; } public bool Equals(testedge other) { return this.a == other.a && this.b == other.b; } } static public bool debug_output; static LockFreeDictionary<int, testedge> d_gs; static public volatile bool f_stop = false; static void Main(string[] args) { debug_output = Debugger.IsAttached; debug_output = false; int c_tasks = Environment.ProcessorCount; //c_tasks = 1; //c_tasks = 2; long c_op_total = 0; TimeSpan ts_total = new TimeSpan(); int i = 0; while (true) { counts c = new counts(); do { d_gs = null; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); Thread.Sleep(10); d_gs = new LockFreeDictionary<int, testedge>(); if (debug_output) d_gs.m_options |= LockFreeDictionary<int, testedge>.Options.DebugOutput; #if DEBUG if (debug_output) { Console.WriteLine("=============== start {0} =================", i); Console.Out.Flush(); } #endif f_stop = false; Task<counts>[] tasks = new Task<counts>[c_tasks]; for (int z = 0; z < tasks.Length; z++) { int _z = z; tasks[z] = Task.Factory.StartNew<counts>(() => Test(_z)); } for (int z = 0; z < tasks.Length; z++) { try { c += tasks[z].Result; } catch (AggregateException aex) { throw aex.Flatten().InnerException; } } #if DEBUG d_gs.m_config.CheckBuckets(); if (debug_output) Console.WriteLine("check... ok"); #endif // Console.ReadKey(); // f_stop = true; //Task.WaitAll(tasks); d_gs = null; tasks = null; } //while (++i % 500 != 0); while (++i == 0); long c_tot = c.add + c.get + c.update + c.remove; double mops = (c_tot / 1000.0) / c.ts.TotalMilliseconds; c_op_total += c_tot; ts_total += c.ts; double mops_tot = (c_op_total / 1000.0) / ts_total.TotalMilliseconds; Console.WriteLine("{0,6} {1,8:d\\:hh\\:mm\\:ss} add: {2,11:#,#} get: {3,11:#,#} upd: {4,11:#,#} rem: {5,11:#,#} tot: {6,11:#,#} {7:N4} {8:N4}", i, c.ts, c.add, c.get, c.update, c.remove, c_tot, mops, mops_tot); } } struct counts { public long add; public long get; public long update; public long remove; public TimeSpan ts; public static counts operator +(counts a, counts b) { counts c = new counts(); c.add = a.add + b.add; c.get = a.get + b.get; c.update = a.update + b.update; c.remove = a.remove + b.remove; c.ts = a.ts + b.ts; return c; } } static counts Test(int num) { counts counts = new Program.counts(); int iter = 0; Random rnd = new Random(Guid.NewGuid().ToByteArray()[0]); Dictionary<int, testedge> netd = new Dictionary<int, testedge>(); Stopwatch stopw = new Stopwatch(); while (!f_stop) { stopw.Start(); int c = d_gs.Count; stopw.Stop(); if (c >= 10000) break; int r = rnd.Next(3); if ((netd.Count > 0 && r == 0))// || netd.Count > 200) { // remove and check KeyValuePair<int,testedge> kvp = netd.ElementAt(rnd.Next(netd.Count)); testedge got_val; stopw.Start(); bool b = d_gs.TryGetValue(kvp.Key, out got_val); stopw.Stop(); counts.get++; if (!b) { Console.ForegroundColor = ConsoleColor.Red; int retry = 0; do { Console.WriteLine("remove: didn't get {0} {1}\r\npause and retry #{2}...", kvp.Key, kvp.Value, retry); Thread.Sleep(10); if (d_gs.TryGetValue(kvp.Key, out got_val)) { Console.WriteLine("ok!"); Console.Out.Flush(); Console.ResetColor(); goto ok; } } while (retry++ < 5); Console.Out.Flush(); Console.ResetColor(); netd.Remove(kvp.Key); continue; } ok: if (!kvp.Value.Equals(got_val)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("remove: wrong value for {0} {1} : got {2}", kvp.Key, kvp.Value, got_val); Console.Out.Flush(); Console.ResetColor(); } stopw.Start(); b = d_gs.TryRemove(kvp.Key, out got_val); stopw.Stop(); counts.remove++; if (!b) { Console.Beep(); Console.Beep(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("couldn't remove confirmed value {0} {1}", kvp.Key, got_val); Console.Out.Flush(); Console.ResetColor(); } else { if (!got_val.Equals(kvp.Value)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("wrong value during removal {0} {1} : got {2}", kvp.Key, kvp.Value, got_val); Console.Out.Flush(); Console.ResetColor(); } if (!netd.Remove(kvp.Key)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("remove error in the .NET reference dict {0} {1} : got {2}", kvp.Key, kvp.Value); Console.Out.Flush(); Console.ResetColor(); } } } else if (netd.Count > 0 && r == 1) { var kvp = netd.ElementAt(rnd.Next(netd.Count)); testedge got_val; stopw.Start(); bool b = d_gs.TryGetValue(kvp.Key, out got_val); stopw.Stop(); counts.get++; if (!b) { Console.ForegroundColor = ConsoleColor.Red; int retry = 0; do { Console.WriteLine("update1: didn't get {0} {1}\r\npause and retry #{2}...", kvp.Key, kvp.Value, retry); Thread.Sleep(10); if (d_gs.TryGetValue(kvp.Key, out got_val)) { Console.WriteLine("ok!"); Console.Out.Flush(); Console.ResetColor(); goto ok1; } } while (retry++ < 5); Console.Out.Flush(); Console.ResetColor(); netd.Remove(kvp.Key); continue; } ok1: if (!kvp.Value.Equals(got_val)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("update1: wrong value for {0} {1} : got {2}", kvp.Key, kvp.Value, got_val); Console.Out.Flush(); Console.ResetColor(); } testedge s_new = new testedge(rnd); stopw.Start(); d_gs[kvp.Key] = s_new; stopw.Stop(); counts.update++; netd[kvp.Key] = s_new; stopw.Start(); b = d_gs.TryGetValue(kvp.Key, out got_val); stopw.Stop(); counts.get++; if (!b) { Console.ForegroundColor = ConsoleColor.Red; int retry = 0; do { Console.WriteLine("update2: didn't get {0} {1}\r\npause and retry #{2}...", kvp.Key, s_new, retry); Thread.Sleep(10); if (d_gs.TryGetValue(kvp.Key, out got_val)) { Console.WriteLine("ok!"); Console.Out.Flush(); Console.ResetColor(); goto ok2; } } while (retry++ < 5); Console.Out.Flush(); Console.ResetColor(); netd.Remove(kvp.Key); continue; } ok2: if (!s_new.Equals(got_val)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("update2: wrong value for {0} {1} : got {2}", kvp.Key, s_new, got_val); Console.Out.Flush(); Console.ResetColor(); } } else if (r == 2) { // add int k = (rnd.Next(int.MaxValue) & unchecked((int)0xFFFFFFF0)) | num; testedge v = new testedge(rnd); if (netd.ContainsKey(k)) { stopw.Start(); bool b = d_gs.ContainsKey(k); stopw.Stop(); counts.get++; if (!b) { Console.Beep(); Console.Beep(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("selected Add key from control dict not found {0}", k); Console.Out.Flush(); Console.ResetColor(); } } else { stopw.Start(); bool b = d_gs.TryAdd(k, v); stopw.Stop(); counts.add++; if (!b) { Console.Beep(); Console.Beep(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("add error {0} {1}", k, v); Console.Out.Flush(); Console.ResetColor(); } netd.Add(k, v); } } iter++; } counts.ts = stopw.Elapsed; f_stop = true; return counts; } }