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;
}
}