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