예제 #1
0
        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();
        }