private void Load_test(Func <TransactionalQueue <XDoc> > ctor) { var rand = new Random(); var queue = new QHandle(ctor); try { var pending = new Queue <ITransactionalQueueEntry <XDoc> >(); var n = 10000; var w = 10; var start = new int[n * w]; var end = new HashSet <int>(); var expired = 0; var dropped = 0; var enqueued = 0; bool done = false; var trigger = new ManualResetEvent(false); var results = new List <Result>(); int v = 0; for (var i = 0; i < w; i++) { var values = new List <int>(); for (var j = 0; j < n; j++) { values.Add(v); start[v] = v; v++; } results.Add(AsyncUtil.ForkThread(() => { trigger.WaitOne(); foreach (var vx in values) { queue.Execute(q => q.Enqueue(new XDoc("doc").Attr("id", vx).Elem("rand", StringUtil.CreateAlphaNumericKey(rand.Next(2, 8))))); Interlocked.Increment(ref enqueued); Thread.Sleep(rand.Next(0, 1)); } }, new Result())); } for (var i = 0; i < 10; i++) { results.Add(AsyncUtil.ForkThread(() => { trigger.WaitOne(); while (!done) { ITransactionalQueueEntry <XDoc> vx = null; queue.Execute(q => vx = q.Dequeue()); if (vx == null) { Thread.Sleep(1000); continue; } lock (pending) { pending.Enqueue(vx); } } }, new Result())); } for (var i = 0; i < 5; i++) { results.Add(AsyncUtil.ForkThread(() => { trigger.WaitOne(); while (!done) { ITransactionalQueueEntry <XDoc> vx = null; lock (pending) { if (pending.Count == 0) { Thread.Sleep(1); continue; } vx = pending.Dequeue(); } var success = false; queue.Execute(q => success = q.CommitDequeue(vx.Id)); if (!success) { Interlocked.Increment(ref expired); continue; } lock (end) { end.Add(vx.Value["@id"].AsInt ?? -1); } } }, new Result())); } results.Add(AsyncUtil.ForkThread(() => { trigger.WaitOne(); while (!done) { ITransactionalQueueEntry <XDoc> vx = null; lock (pending) { if (pending.Count == 0) { Thread.Sleep(1000); continue; } vx = pending.Dequeue(); } queue.Execute(q => q.RollbackDequeue(vx.Id)); Interlocked.Increment(ref dropped); Thread.Sleep(500); } }, new Result())); trigger.Set(); int waitCounter = 0; while (end.Count != start.Length) { var qcount = 0; queue.Execute(q => qcount = q.Count); Console.WriteLine("enqueued: {0}, queue size: {1}, output size: {2}, dropped items: {3}, expired items: {4}", enqueued, qcount, end.Count, dropped, expired); foreach (var r in results) { if (r.HasException) { r.Wait(); } } Thread.Sleep(1000); waitCounter++; if (waitCounter > 5) { waitCounter = 0; Console.WriteLine("refreshing queue"); queue.Refresh(); } } done = true; foreach (var r in results) { r.Wait(); } Assert.AreEqual(start, (from x in end orderby x select x).ToArray()); Console.WriteLine("total queue items expired: {0}", expired); } finally { queue.Dispose(); } }
private void Load_test(Func<TransactionalQueue<XDoc>> ctor) { var rand = new Random(); var queue = new QHandle(ctor); try { var pending = new Queue<ITransactionalQueueEntry<XDoc>>(); var n = 10000; var w = 10; var start = new int[n * w]; var end = new HashSet<int>(); var expired = 0; var dropped = 0; var enqueued = 0; bool done = false; var trigger = new ManualResetEvent(false); var results = new List<Result>(); int v = 0; for(var i = 0; i < w; i++) { var values = new List<int>(); for(var j = 0; j < n; j++) { values.Add(v); start[v] = v; v++; } results.Add(Async.ForkThread(() => { trigger.WaitOne(); foreach(var vx in values) { queue.Execute(q => q.Enqueue(new XDoc("doc").Attr("id", vx).Elem("rand", StringUtil.CreateAlphaNumericKey(rand.Next(2, 8))))); Interlocked.Increment(ref enqueued); Thread.Sleep(rand.Next(0, 1)); } }, new Result())); } for(var i = 0; i < 10; i++) { results.Add(Async.ForkThread(() => { trigger.WaitOne(); while(!done) { ITransactionalQueueEntry<XDoc> vx = null; queue.Execute(q => vx = q.Dequeue()); if(vx == null) { Thread.Sleep(1000); continue; } lock(pending) { pending.Enqueue(vx); } } }, new Result())); } for(var i = 0; i < 5; i++) { results.Add(Async.ForkThread(() => { trigger.WaitOne(); while(!done) { ITransactionalQueueEntry<XDoc> vx = null; lock(pending) { if(pending.Count == 0) { Thread.Sleep(1); continue; } vx = pending.Dequeue(); } var success = false; queue.Execute(q => success = q.CommitDequeue(vx.Id)); if(!success) { Interlocked.Increment(ref expired); continue; } lock(end) { end.Add(vx.Value["@id"].AsInt ?? -1); } } }, new Result())); } results.Add(Async.ForkThread(() => { trigger.WaitOne(); while(!done) { ITransactionalQueueEntry<XDoc> vx = null; lock(pending) { if(pending.Count == 0) { Thread.Sleep(1000); continue; } vx = pending.Dequeue(); } queue.Execute(q => q.RollbackDequeue(vx.Id)); Interlocked.Increment(ref dropped); Thread.Sleep(500); } }, new Result())); trigger.Set(); int waitCounter = 0; while(end.Count != start.Length) { var qcount = 0; queue.Execute(q => qcount = q.Count); Console.WriteLine("enqueued: {0}, queue size: {1}, output size: {2}, dropped items: {3}, expired items: {4}", enqueued, qcount, end.Count, dropped, expired); foreach(var r in results) { if(r.HasException) { r.Wait(); } } Thread.Sleep(1000); waitCounter++; if(waitCounter > 5) { waitCounter = 0; Console.WriteLine("refreshing queue"); queue.Refresh(); } } done = true; foreach(var r in results) { r.Wait(); } Assert.AreEqual(start, (from x in end orderby x select x).ToArray()); Console.WriteLine("total queue items expired: {0}", expired); } finally { queue.Dispose(); } }