using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Linq; class Program { static public bool debug_output; public class TestException : Exception { } //static LockFreeDictionary<String, String> d_ss = new LockFreeDictionary<String, String>(); //static LockFreeDictionary<int, String> d_is = new LockFreeDictionary<int, String>(); static LockFreeDictionary<Guid, String> d_gs = new LockFreeDictionary<Guid, string>(); static public bool f_stop = false; static string GetRandomString(Random r) { return ""; } static void Main(string[] args) { debug_output = Debugger.IsAttached; //debug_output = false; //int? i = null; //int? j = null; //bool zzz = i.Equals(null); //Nullable.Equals(i, j); //var z = new Dictionary<String, String>(); //z.Add("foo", "bar"); //z.Add("foo", "bar"); //d_ss.Add("Hello", "Lock-free"); //Debug.Assert(d_ss["Hello"] == "Lock-free"); //Test(); #if false //unchecked { ulong h = 0;// 0xaaaaaaaaaaaaaaaa; while (true) { h ^= 0x55555555aaaaaaaa; h ^= 0xaaaaaaaa55555555; if (h != 0xffffffffffffffff) Debugger.Break(); } } #endif #if false unchecked { long m_tail = 0; long new_tail; long tail = 0x0000170e000000e9; int gx = -1; while (true) { /// the tail needs to be advanced new_tail = tail + 0x0000000100000000; new_tail &= (long)0xFFFFFFFF00000000; new_tail |= (uint)gx; if ((new_tail & 0x0ff0) == 0x0ff0) { Debugger.Break(); } //Int64 prev = Interlocked.CompareExchange(ref m_tail, new_tail, tail); } } #endif //LockFreeDictionary<int, String> foo = new LockFreeDictionary<int, string>(); //foo.Add(99, "hello"); // d_gs.m_config.TestFreelist(); // Environment.Exit(0); #if false d_is.Add(99999, "five nines"); d_is.Add(13, "first"); d_is.Add(50, "second"); d_is.Add(87, "third"); d_is.Add(124, "fourth"); d_is.Add(161, "fifth"); String s; Debug.Assert(d_is.TryRemove(87, out s)); #endif #if false Int64 h = 0; Action a1 = () => { while (true) { Interlocked.Exchange(ref h, 0x2aaaaaaaaaaaaaaa); Interlocked.Exchange(ref h, 0x5555555555555555); } }; Action a2 = () => { while (true) { Int64 i = Read64(ref h); if (i != 0x2aaaaaaaaaaaaaaa && i != 0x5555555555555555) throw new Exception("immediately fails with a torn read on 32-bit .NET"); } }; Task.Factory.StartNew(a1); Task.Factory.StartNew(a1); Task.Factory.StartNew(a1); Task.Factory.StartNew(a2); Console.ReadKey(); //d_ss.m_config.Test(); #endif //Console.WriteLine(d_is.m_config.Dump()); //Guid gg = Guid.NewGuid(); //d_gs.Add(gg, "abcd"); //d_gs.TryUpdate(gg, String.Intern("efgh"), "abcd"); // Test(); int c_tasks = Environment.ProcessorCount; //c_tasks = 1; Task<counts>[] tasks; int i = 0; while (true) { counts c = new counts(); do { //GC.Collect(3, GCCollectionMode.Forced); tasks = new Task<counts>[c_tasks]; d_gs = new LockFreeDictionary<Guid, string>(); if (debug_output) d_gs.m_options |= LockFreeDictionary<Guid, string>.Options.DebugOutput; if (debug_output) { Console.WriteLine("=============== start {0} =================", i); Console.Out.Flush(); } f_stop = false; for (int z = 0; z < tasks.Length; 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) { if (!(aex.Flatten().InnerException is TestException)) throw; } #if false catch { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("failed"); Console.Out.Flush(); Console.ResetColor(); break; } #endif } var cfg = d_gs.m_config; // Task.Factory.StartNew(() => // { cfg.CheckBuckets(); if (debug_output) Console.WriteLine("check... ok"); //}); // Console.ReadKey(); // f_stop = true; //Task.WaitAll(tasks); d_gs = null; tasks = null; } while (++i % 500 != 0); long c_tot = c.add + c.get + c.update + c.remove; double mops = c.ts.TotalMilliseconds == 0 ? double.PositiveInfinity : (c_tot / 1000.0) / c.ts.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} Mop/s", i, c.ts, c.add, c.get, c.update, c.remove, c_tot, mops); } } 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 public ManualResetEvent mre_go = new ManualResetEvent(true); static counts Test(int num) { counts counts = new Program.counts(); int iter = 0; Random rnd = new Random(Guid.NewGuid().ToByteArray()[0]); Dictionary<Guid, String> netd = new Dictionary<Guid, string>(); Stopwatch stopw = new Stopwatch(); while (!f_stop) { stopw.Start(); int c = d_gs.Count; stopw.Stop(); if (c >= 700) break; //mre_go.WaitOne(); int r = rnd.Next(3); if ((netd.Count > 0 && r == 0))// || netd.Count > 200) { // remove and check var kvp = netd.ElementAt(rnd.Next(netd.Count)); String 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 != 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 != 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)); String 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 != 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(); } String s_new = Guid.NewGuid().ToString();// new String(Enumerable.Range(0, rnd.Next(1, 100)).Select(w => (Char)rnd.Next(32, 123)).ToArray()); 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 != 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 var rgb = Guid.NewGuid().ToByteArray(); rgb[0] = (byte)num; Guid k = new Guid(rgb); String v = k.ToString();// new String(Enumerable.Range(0, rnd.Next(100)).Select(w => (Char)rnd.Next(32, 123)).ToArray()); 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++; if (num == 1) { //if (iter % 1000 == 0) //Console.WriteLine("{0} {1,-4} {2,-4}", iter, netd.Count, d_gs.m_config.m_c_free); #if false if (iter == 100) { d_gs.m_config.Verify(); } #endif #if false if (iter == 200000) { f_stop = true; Thread.Sleep(15); Console.WriteLine(d_gs.m_config.Dump()); Console.Out.Flush(); Debugger.Break(); } #endif //if (iter % 10000 == 0) //Console.WriteLine("{0}", d_gs.m_config.m_c_free); #if false if (iter == 1000) { // f_stop = true; Thread.Sleep(15); Console.WriteLine(d_gs.m_config.Dump()); Debugger.Break(); } #endif } // if (iter == 500000) //return; } counts.ts = stopw.Elapsed; f_stop = true; return counts; } }