using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Linq; using System.Runtime.InteropServices; abstract class Tester<K, V> : IDisposable where K : IEquatable<K> where V : IEquatable<V> { protected IDictionary<K, V> test_dict; protected volatile bool f_stop = false; protected Func<int, Random, K> key_getter; protected Func<int, Random, V> value_getter; protected int ms_timeout = Timeout.Infinite; protected int c_iter = 1; int c_tasks; String dict_name; public Tester( int c_tasks, Func<int, Random, K> key_getter, Func<int, Random, V> value_getter, Type t_gen_dict) { this.c_tasks = c_tasks; this.key_getter = key_getter; this.value_getter = value_getter; this.dict_name = t_gen_dict.Name.Replace("`2", ""); Type tg = t_gen_dict.MakeGenericType(new Type[] { typeof(K), typeof(V) }); test_dict = (IDictionary<K, V>)Activator.CreateInstance(tg, new Object[] { }); } public void StartTest() { Thread.Sleep(1000); Console.Write("{0,30} {1,25} {2,9} {3,9} {4,2}", this.GetType().Name.Replace("`2", ""), dict_name, typeof(K).Name, typeof(V).Name, c_tasks); Counts c = new Counts(); for (int iter = 0; iter < c_iter; iter++) { Task<Counts>[] tasks = new Task<Counts>[c_tasks]; f_stop = false; for (int z = 0; z < tasks.Length; z++) { int _z = z; tasks[z] = Task.Factory.StartNew<Counts>(() => RunTest(_z)); } if (ms_timeout != Timeout.Infinite) { Thread.Sleep(ms_timeout); f_stop = true; } for (int z = 0; z < tasks.Length; z++) { c += tasks[z].Result; } if (c_iter > 1) { Console.Write("."); test_dict.Clear(); } } double c_tot = c.add + c.get + c.update + c.remove; double mops = (c_tot / 1000.0) / c.ts.TotalMilliseconds; #if true Console.WriteLine(" {0,8:N4}", mops); #else Console.WriteLine("{0,8:mm\\:ss\\.ffffff} add: {1,11:#,#} get: {2,11:#,#} upd: {3,11:#,#} rem: {4,11:#,#} tot: {5,11:#,#} {6:N4} Mop/s", c.ts, c.add, c.get, c.update, c.remove, c_tot, mops); Console.WriteLine(); #endif } public abstract Counts RunTest(int num); public void Dispose() { key_getter = null; value_getter = null; test_dict = null; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); } }; class _45SecondRandomUsageTest<K, V> : Tester<K, V> where K : IEquatable<K> where V : IEquatable<V> { protected int max_items = int.MaxValue; public _45SecondRandomUsageTest(int c_tasks, Func<int, Random, K> key_getter, Func<int, Random, V> value_getter, Type t_gen_dict) : base(c_tasks, key_getter, value_getter, t_gen_dict) { ms_timeout = 45000; } public override Counts RunTest(int num) { Counts counts = new Counts(); Random rnd = new Random(Guid.NewGuid().ToByteArray()[0]); Dictionary<K, V> control_dict = new Dictionary<K, V>(); Stopwatch stopw = new Stopwatch(); while (!f_stop) { // count stopw.Start(); int c = test_dict.Count; stopw.Stop(); int r = rnd.Next(3); if ((control_dict.Count > 0 && r == 0)) { // get - remove KeyValuePair<K, V> kvp = control_dict.ElementAt(rnd.Next(control_dict.Count)); V got_val; stopw.Start(); if (!test_dict.TryGetValue(kvp.Key, out got_val)) throw new Exception(); stopw.Stop(); counts.get++; stopw.Start(); test_dict.Remove(kvp.Key); stopw.Stop(); counts.remove++; control_dict.Remove(kvp.Key); } else if (control_dict.Count > 0 && r == 1) { // get - update - get var kvp = control_dict.ElementAt(rnd.Next(control_dict.Count)); V got_val; stopw.Start(); if (!test_dict.TryGetValue(kvp.Key, out got_val)) throw new Exception(); stopw.Stop(); counts.get++; V s_new = value_getter(num, rnd); stopw.Start(); test_dict[kvp.Key] = s_new; stopw.Stop(); counts.update++; control_dict[kvp.Key] = s_new; stopw.Start(); if (!test_dict.TryGetValue(kvp.Key, out got_val)) throw new Exception(); stopw.Stop(); counts.get++; } else if (r == 2 && c < max_items) { // get - add K k = key_getter(num, rnd); V v = value_getter(num, rnd); if (control_dict.ContainsKey(k)) { stopw.Start(); if (!test_dict.ContainsKey(k)) throw new Exception(); stopw.Stop(); counts.get++; } else { stopw.Start(); test_dict.Add(k, v); stopw.Stop(); counts.add++; control_dict.Add(k, v); } } } counts.ts = stopw.Elapsed; f_stop = true; return counts; } }; class _45Sec10000MaxUsageTest<K, V> : _45SecondRandomUsageTest<K, V> where K : IEquatable<K> where V : IEquatable<V> { public _45Sec10000MaxUsageTest(int c_tasks, Func<int, Random, K> key_getter, Func<int, Random, V> value_getter, Type t_gen_dict) : base(c_tasks, key_getter, value_getter, t_gen_dict) { max_items = 10000; } }; class Add10E6Test<K, V> : Tester<K, V> where K : IEquatable<K> where V : IEquatable<V> { public Add10E6Test(int c_tasks, Func<int, Random, K> key_getter, Func<int, Random, V> value_getter, Type t_gen_dict) : base(c_tasks, key_getter, value_getter, t_gen_dict) { } public override Counts RunTest(int num) { Counts counts = new Counts(); Random rnd = new Random(Guid.NewGuid().ToByteArray()[0]); Stopwatch stopw = new Stopwatch(); while (test_dict.Count < 10E6) { K k = key_getter(num, rnd); V v = value_getter(num, rnd); if (!test_dict.ContainsKey(k)) { stopw.Start(); test_dict.Add(k, v); stopw.Stop(); counts.add++; } } counts.ts = stopw.Elapsed; f_stop = true; return counts; } }; class _60SecReadOnly1E5Test<K, V> : Tester<K, V> where K : IEquatable<K> where V : IEquatable<V> { Random rnd = new Random(Guid.NewGuid().ToByteArray()[0]); List<K> keys = new List<K>(); public _60SecReadOnly1E5Test(int c_tasks, Func<int, Random, K> key_getter, Func<int, Random, V> value_getter, Type t_gen_dict) : base(c_tasks, key_getter, value_getter, t_gen_dict) { ms_timeout = 45000; while (test_dict.Count < 1E5)//1E6) { K k = key_getter(0, rnd); if (!test_dict.ContainsKey(k)) { test_dict.Add(k, value_getter(0, rnd)); keys.Add(k); } } } public override Counts RunTest(int num) { Counts counts = new Counts(); Stopwatch stopw = new Stopwatch(); while (!f_stop) { K k = keys[rnd.Next(keys.Count)]; stopw.Start(); V v = test_dict[k]; stopw.Stop(); counts.get++; } counts.ts = stopw.Elapsed; f_stop = true; return counts; } }; class _RandomUsageTestTo1000<K, V> : Tester<K, V> where K : IEquatable<K> where V : IEquatable<V> { protected int max_items = int.MaxValue; public _RandomUsageTestTo1000(int c_tasks, Func<int, Random, K> key_getter, Func<int, Random, V> value_getter, Type t_gen_dict) : base(c_tasks, key_getter, value_getter, t_gen_dict) { c_iter = 3; } public override Counts RunTest(int num) { Counts counts = new Counts(); Random rnd = new Random(Guid.NewGuid().ToByteArray()[0]); Dictionary<K, V> control_dict = new Dictionary<K, V>(); Stopwatch stopw = new Stopwatch(); while (!f_stop) { // count stopw.Start(); int c = test_dict.Count; stopw.Stop(); if (c > 1000) break; int r = rnd.Next(3); if ((control_dict.Count > 0 && r == 0)) { // get - remove KeyValuePair<K, V> kvp = control_dict.ElementAt(rnd.Next(control_dict.Count)); V got_val; stopw.Start(); if (!test_dict.TryGetValue(kvp.Key, out got_val)) throw new Exception(); stopw.Stop(); counts.get++; stopw.Start(); test_dict.Remove(kvp.Key); stopw.Stop(); counts.remove++; control_dict.Remove(kvp.Key); } else if (control_dict.Count > 0 && r == 1) { // get - update - get var kvp = control_dict.ElementAt(rnd.Next(control_dict.Count)); V got_val; stopw.Start(); if (!test_dict.TryGetValue(kvp.Key, out got_val)) throw new Exception(); stopw.Stop(); counts.get++; V s_new = value_getter(num, rnd); stopw.Start(); test_dict[kvp.Key] = s_new; stopw.Stop(); counts.update++; control_dict[kvp.Key] = s_new; stopw.Start(); if (!test_dict.TryGetValue(kvp.Key, out got_val)) throw new Exception(); stopw.Stop(); counts.get++; } else if (r == 2 && c < max_items) { // get - add K k = key_getter(num, rnd); V v = value_getter(num, rnd); if (control_dict.ContainsKey(k)) { stopw.Start(); if (!test_dict.ContainsKey(k)) throw new Exception(); stopw.Stop(); counts.get++; } else { stopw.Start(); test_dict.Add(k, v); stopw.Stop(); counts.add++; control_dict.Add(k, v); } } } counts.ts = stopw.Elapsed; f_stop = true; return counts; } };