public void Perf_test_multi_thread_put_peek_and_take(ITransactionalQueue <XDoc> queue) { long totalEnqueue = 0; long totalDequeue = 0; var w = 5; var n = 5000; var m = 4; for (var k = 0; k < m; k++) { var enqueues = new List <Result>(); var trigger = new ManualResetEvent(false); for (var i = 0; i < w; i++) { enqueues.Add(AsyncUtil.ForkThread(() => Enqueue(queue, n, trigger), new Result())); } var stopwatch = Stopwatch.StartNew(); trigger.Set(); foreach (var r in enqueues) { r.Wait(); } stopwatch.Stop(); Assert.AreEqual(n * w, queue.Count); totalEnqueue += stopwatch.ElapsedMilliseconds; var j = 0; var dequeues = new List <Result <int> >(); trigger.Reset(); for (var i = 0; i < w; i++) { dequeues.Add(AsyncUtil.ForkThread(() => Dequeue(queue, trigger), new Result <int>())); } stopwatch = Stopwatch.StartNew(); trigger.Set(); foreach (var r in dequeues) { j += r.Wait(); } stopwatch.Stop(); totalDequeue += stopwatch.ElapsedMilliseconds; Assert.AreEqual(0, queue.Count); Assert.AreEqual(n * w, j); } Console.WriteLine("Enqueue: {0:0,000}/s", n * m * 1000 / totalEnqueue); Console.WriteLine("Dequeue: {0:0,000}/s", n * m * 1000 / totalDequeue); }
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(); } }
public void QueueWorkItem(Action callback) { LastItem = AsyncUtil.ForkThread(callback, new Result()); }