public static void ConcurrentSearchTest(ConcurrentRBTree <long, Data> rbTree, int numOfThreads, long searchOperationsPerThread, long nodesMaxKeyValue) { Console.WriteLine("************* Search Test ***************"); Console.WriteLine(); Console.WriteLine($"Total threads: {numOfThreads}"); Console.WriteLine($"We will perform {searchOperationsPerThread} search operations on each thread"); Console.WriteLine(); var threads = new Thread[numOfThreads]; for (var i = 0; i < numOfThreads; i++) { threads[i] = new Thread(() => { var rand = new Random(); for (var j = 0; j < searchOperationsPerThread; j++) { var target = 1 + (long)(rand.NextDouble() * nodesMaxKeyValue); _ = rbTree.GetData(target); } }); } // search test var watch = new Stopwatch(); watch.Start(); foreach (var thread in threads) { thread.Start(); } foreach (var thread in threads) { thread.Join(); } watch.Stop(); Console.WriteLine($"Total time spent in search: {watch.ElapsedMilliseconds} ms"); Console.WriteLine(); Console.WriteLine(); }
public static void ConcurrentDeleteTest(ConcurrentRBTree <long, Data> rbTree, int numOfThreads, int nodesPerThread, int totalNodesToDelete, long nodesMaxKeyValue) { if (rbTree.isValidRBT(nodesMaxKeyValue + 1) == false) { Console.WriteLine($"After insertion, RBT is invalid"); Debug.Assert(!rbTree.isValidRBT(nodesMaxKeyValue + 1)); } //rbTree.printLevelOrder(); Console.WriteLine("************* Delete Test ***************"); Console.WriteLine(); Console.WriteLine($"We will perform {totalNodesToDelete} delete operations"); Console.WriteLine(); // generate valid deletable items var count = 0; var deleteItems = new HashSet <long>(); var rand = new Random(); while (true) { long target; while (true) { target = 1 + (long)(rand.NextDouble() * nodesMaxKeyValue); if (!deleteItems.Contains(target)) { break; } } var data = rbTree.GetData(target); if (data != null) { deleteItems.Add(data.Item1); count++; } if (count == totalNodesToDelete) { break; } } var keysToDelete = deleteItems.ToArray(); var threads = new Thread[numOfThreads]; for (var i = 0; i < threads.Length; i++) { var iLocal = i; threads[i] = new Thread(() => { var start = iLocal * nodesPerThread; var end = start + nodesPerThread - 1; for (var j = start; j <= end; j++) { rbTree.Remove(keysToDelete[j]); } }); threads[i].Name = i.ToString(); } Console.WriteLine($"Total nodes to delete: {totalNodesToDelete}"); Console.WriteLine($"Total threads: {numOfThreads}"); Console.WriteLine($"Total nodes per thread: {nodesPerThread}"); Console.WriteLine(); // starting deletes var watch = new Stopwatch(); watch.Start(); foreach (var thread in threads) { thread.Start(); } foreach (var thread in threads) { thread.Join(); } watch.Stop(); if (rbTree.isValidRBT(nodesMaxKeyValue + 1) == false) { Console.WriteLine($"After delete, RBT is invalid"); } Console.WriteLine($"Total time spent in deletion: {watch.ElapsedMilliseconds} ms"); Console.WriteLine(); Console.WriteLine($"Node count after deletion: {(rbTree.Count())}"); Console.WriteLine(); Console.WriteLine($"Tree depth: {rbTree.MaxDepth()}"); Console.WriteLine(); Console.WriteLine(); }
public static void ConcurrentInsertDeleteTest(ConcurrentRBTree <long, Data> rbTree, long totalNodesInTree, int numOfThreads, int nodesPerThread, long totalNodesToDelete, long totalNodesToInsert, long nodesMaxKeyValue) { Console.WriteLine("************* Create Tree ***************"); Console.WriteLine(); ConcurrentInsertTest(rbTree, 12, totalNodesInTree / 12, totalNodesInTree, nodesMaxKeyValue, false); Console.WriteLine($"Node count of tree: {(rbTree.Count())}"); Console.WriteLine(); Console.WriteLine($"Tree depth: {rbTree.MaxDepth()}"); Console.WriteLine(); Console.WriteLine(); // generate valid deletable items var deleteCount = 0; var deleteItems = new HashSet <long>(); var rand = new Random(); while (true) { long target; while (true) { target = 1 + (long)(rand.NextDouble() * nodesMaxKeyValue); if (!deleteItems.Contains(target)) { break; } } var data = rbTree.GetData(target); if (data != null) { deleteItems.Add(data.Item1); deleteCount++; } if (deleteCount == totalNodesToDelete) { break; } } var keysToDelete = deleteItems.ToArray(); var deleteThreads = new Thread[numOfThreads]; for (var i = 0; i < deleteThreads.Length; i++) { var iLocal = i; deleteThreads[i] = new Thread(() => { var start = iLocal * nodesPerThread; var end = start + nodesPerThread - 1; for (var j = start; j <= end; j++) { rbTree.Remove(keysToDelete[j]); } }); deleteThreads[i].Name = i.ToString(); } // generate valid insertable items var insertCount = 0; var insertItems = new HashSet <long>(); while (true) { long target; while (true) { target = 1 + (long)(rand.NextDouble() * nodesMaxKeyValue); if (!insertItems.Contains(target)) { break; } } var data = rbTree.GetData(target); if (data == null) { insertItems.Add(target); insertCount++; } if (insertCount == totalNodesToInsert) { break; } } var values = insertItems.Select(i => new Tuple <long, Data>(i, new Data { Value = i.ToString() })).ToArray(); var insertThreads = new Thread[numOfThreads]; for (var i = 0; i < insertThreads.Length; i++) { var iLocal = i; insertThreads[i] = new Thread(() => { var start = iLocal * nodesPerThread; var end = start + nodesPerThread - 1; for (var j = start; j <= end; j++) { rbTree.Add(values[j].Item1, values[j].Item2); } }); insertThreads[i].Name = i.ToString(); } Console.WriteLine("************* Insert-Delete Test ***************"); Console.WriteLine(); Console.WriteLine($"Total nodes to insert: {totalNodesToInsert}"); Console.WriteLine($"Total nodes to delete: {totalNodesToDelete}"); Console.WriteLine($"Total threads: {numOfThreads}"); Console.WriteLine($"Total nodes per thread: {nodesPerThread}"); Console.WriteLine(); // starting inserts var watch = new Stopwatch(); watch.Start(); for (var i = 0; i < numOfThreads; i++) { insertThreads[i].Start(); deleteThreads[i].Start(); } for (var i = 0; i < numOfThreads; i++) { insertThreads[i].Join(); deleteThreads[i].Join(); } watch.Stop(); Console.WriteLine($"Total time spent in simultaneous insertion & deletion: {watch.ElapsedMilliseconds} ms"); Console.WriteLine(); Console.WriteLine($"Node count after insertion: {(rbTree.Count())}"); Console.WriteLine(); Console.WriteLine($"Tree depth: {rbTree.MaxDepth()}"); Console.WriteLine(); Console.WriteLine(); }