Exemplo n.º 1
0
		static void Main(string[] args)
		{
			Console.Clear();
			Console.WriteLine("Before starting, be sure you compile the application in release mode");
			Console.WriteLine("and that you execute it OUTSIDE Visual Studio. If you run inside");
			Console.WriteLine("the application code will be slower than the .Net base libraries,");
			Console.WriteLine("as the base libraries are never debugable and the application is,");
			Console.WriteLine("even if optimizations are \"active\".");
			Console.WriteLine();
			Console.WriteLine("Also, if the sample crashes with OutOfMemoryExceptions, you will need");
			Console.WriteLine("to change its constants. Sorry for that, but I wanted an extreme");
			Console.WriteLine("situation, which can be too extreme.");
			Console.WriteLine();
			Console.WriteLine("Press enter to start the tests.");
			Console.ReadLine();

			while(true)
			{
                Console.Clear();
                Console.WriteLine("First test: We will put " + _COUNT_ITERATIONS_FASTCREATOR + " values on the dictionaries, without");
                Console.WriteLine("any concurrency and using a really fast creator. This one usually gives the");
                Console.WriteLine("best performance to normal dictionaries with the simplest locks. But, as you");
                Console.WriteLine("can see, it is pretty fast for all of them.");
                Console.WriteLine();

                var allSamples = new AllSamples(false, _FastResultCreator);
                allSamples.Run(1, _FastForEach);

                Console.WriteLine();
                Console.WriteLine("Press enter to execute the second test.");
                Console.ReadLine();

                Console.Clear();
                Console.WriteLine("Now we will simple read those dictionaries, without any concurrency.");
                Console.WriteLine("Here the concurrent dictionaries are usually faster as they were");
                Console.WriteLine("created to use lock-Free techniques for reading (they were slower ");
                Console.WriteLine("in the first test exactly because this lock-free support) while normal");
                Console.WriteLine("dictionaries have to use at least read locks. Also, if everything is running");
                Console.WriteLine("as expected, the ReaderWriterLockSlim should be the worst in both tests.");
                Console.WriteLine("This means, the .Net ReaderWriterLockSlim is not that slim.");
				Console.WriteLine("Note that a difference between the dictionaries of the same type");
				Console.WriteLine("that allow duplicates or not is simple luck, as they never create the value.");
                Console.WriteLine();

                allSamples.Run(1, _FastForEach);

                Console.WriteLine();
                Console.WriteLine("Press enter to execute the third test.");
                Console.ReadLine();

                Console.Clear();
                Console.WriteLine("In this third test we will do what it is supposed to do with ");
                Console.WriteLine("concurrent dictionaries or dictionaries + locks. We will access");
                Console.WriteLine("those dictionaries from many threads (ProcessorCount threads*2).");
                Console.WriteLine("In this test the multi-threaded dictionaries should be the winners,");
                Console.WriteLine("usually having very near performance values, while the");
                Console.WriteLine("Normal dictionaries should be ordered from the fastest to the slowest as:");
                Console.WriteLine("SpinReaderWriterLockSlim (my lock), full lock and .Net ReaderWriterLockSlim.");
                Console.WriteLine("Note that the dictionaries are already filled, so it will be no parallel");
                Console.WriteLine("writes. Only parallel reads, and differences on the time of dictionaries");
				Console.WriteLine("that create values in parallel or not are simple luck.");
                Console.WriteLine();

                allSamples.Run(Environment.ProcessorCount*2, _FastForEach);
                allSamples = null;

                Console.WriteLine("Press enter to execute the fourth test.");
                Console.ReadLine();

                Console.Clear();
                Console.WriteLine("Now we will recreate the dictionaries. So, we will execute many threads");
                Console.WriteLine("in parallel, but the fastest threads will not find a value there");
                Console.WriteLine("and will create them. Other threads will use those created values.");
                Console.WriteLine("Here we will see the difference of creating values in parallel or not.");
                Console.WriteLine();

                allSamples = new AllSamples(true, _FastResultCreator);
                allSamples.Run(Environment.ProcessorCount*2, _FastForEach);
                allSamples = null;

                Console.WriteLine("Press enter to execute the fifth test.");
                Console.ReadLine();

                Console.Clear();
                Console.WriteLine("Until now we had one kind of extreme situations. All threads were getting");
				Console.WriteLine("or creating the same values at the same time.");
                Console.WriteLine("But what about threads creating different values and putting them");
                Console.WriteLine("at the same time into the dictionary?");
                Console.WriteLine("This is where I believed ConcurrentDictionaries will do much");
                Console.WriteLine("better, but the reality is: They didn't. They are the worst.");
                Console.WriteLine("But wait for some explanations on the next test.");
				Console.WriteLine();

                allSamples = new AllSamples(true, _FastResultCreator);
                allSamples.Run(Environment.ProcessorCount*2, _FastNonCollidingForEach);
                allSamples = null;

                Console.WriteLine("Press enter to see the sixth test.");
                Console.ReadLine();

				_WaitTenMilliseconds();
                Console.Clear();
                Console.WriteLine("Finally we will have a little reality here (only a little).");
                Console.WriteLine("Our create values until now where really fast. Instantaneous.");
                Console.WriteLine("Why would we use a dictionary to cache results if we can call the");
                Console.WriteLine("delegate that creates the value directly and it will be faster?");
				Console.WriteLine("Ok, there are some cases (like singletons) that you may need, but");
                Console.WriteLine("one of the biggest points of dictionaries is to store data that is");
                Console.WriteLine("slow to create. So, let's create a slow creator. It takes 3 milliseconds");
				Console.WriteLine(" to do its work. That means: " + _iterationsFor3Milliseconds + " unused iterations.");
				Console.WriteLine();

                allSamples = new AllSamples(true, _SlowResultCreator);
                allSamples.Run(_COUNT_MANY_THREADS, _SlowNonCollidingForEach);
                allSamples = null;

                Console.WriteLine("Press enter to go to the final test.");
                Console.ReadLine();

                Console.Clear();
				Console.WriteLine("Now we will have a mix. All the creations will be slow, but some threads");
				Console.WriteLine("will be adding different values while others may be trying to get or create");
				Console.WriteLine("the same values in parallel.");
				Console.WriteLine();

                allSamples = new AllSamples(true, _SlowResultCreator);
                allSamples.Run(_COUNT_MANY_THREADS, _SlowSomeCollisionsForEach);
                allSamples = null;

                Console.WriteLine("Press enter to restart the tests.");
                Console.ReadLine();

				Console.Clear();
				Console.WriteLine("I lied to you. We will not restart the tests yet.");
				Console.WriteLine("But if you really want to do it, it is better. The tests at");
				Console.WriteLine("the second execution usually have a difference, that starts");
				Console.WriteLine("to become a constant. That is, the more you use it, the");
				Console.WriteLine("the results will be nearer the last result.");
				Console.WriteLine();
				Console.WriteLine("My personal conclusion is that normal dictionaries are the fastest");
				Console.WriteLine("ones for insertion. If you can get many values, use a single lock and add");
				Console.WriteLine("them into the dictionary, do it. It is safe and faster than any");
				Console.WriteLine("concurrent alternative.");
				Console.WriteLine();
				Console.WriteLine("But if you need to write from many threads, well, think about");
				Console.WriteLine("probability and constraints. I usually write only a little");
				Console.WriteLine("and read a lot into dictionaries. So, the fastest reader, the better.");
				Console.WriteLine();
                Console.WriteLine("Now, I will stop talking. Press enter to restart the tests.");
                Console.ReadLine();
			}
		}
Exemplo n.º 2
0
        static void Main(string[] args)
        {
            Console.Clear();
            Console.WriteLine("Before starting, be sure you compile the application in release mode");
            Console.WriteLine("and that you execute it OUTSIDE Visual Studio. If you run inside");
            Console.WriteLine("the application code will be slower than the .Net base libraries,");
            Console.WriteLine("as the base libraries are never debugable and the application is,");
            Console.WriteLine("even if optimizations are \"active\".");
            Console.WriteLine();
            Console.WriteLine("Also, if the sample crashes with OutOfMemoryExceptions, you will need");
            Console.WriteLine("to change its constants. Sorry for that, but I wanted an extreme");
            Console.WriteLine("situation, which can be too extreme.");
            Console.WriteLine();
            Console.WriteLine("Press enter to start the tests.");
            Console.ReadLine();

            while (true)
            {
                Console.Clear();
                Console.WriteLine("First test: We will put " + _COUNT_ITERATIONS_FASTCREATOR + " values on the dictionaries, without");
                Console.WriteLine("any concurrency and using a really fast creator. This one usually gives the");
                Console.WriteLine("best performance to normal dictionaries with the simplest locks. But, as you");
                Console.WriteLine("can see, it is pretty fast for all of them.");
                Console.WriteLine();

                var allSamples = new AllSamples(false, _FastResultCreator);
                allSamples.Run(1, _FastForEach);

                Console.WriteLine();
                Console.WriteLine("Press enter to execute the second test.");
                Console.ReadLine();

                Console.Clear();
                Console.WriteLine("Now we will simple read those dictionaries, without any concurrency.");
                Console.WriteLine("Here the concurrent dictionaries are usually faster as they were");
                Console.WriteLine("created to use lock-Free techniques for reading (they were slower ");
                Console.WriteLine("in the first test exactly because this lock-free support) while normal");
                Console.WriteLine("dictionaries have to use at least read locks. Also, if everything is running");
                Console.WriteLine("as expected, the ReaderWriterLockSlim should be the worst in both tests.");
                Console.WriteLine("This means, the .Net ReaderWriterLockSlim is not that slim.");
                Console.WriteLine("Note that a difference between the dictionaries of the same type");
                Console.WriteLine("that allow duplicates or not is simple luck, as they never create the value.");
                Console.WriteLine();

                allSamples.Run(1, _FastForEach);

                Console.WriteLine();
                Console.WriteLine("Press enter to execute the third test.");
                Console.ReadLine();

                Console.Clear();
                Console.WriteLine("In this third test we will do what it is supposed to do with ");
                Console.WriteLine("concurrent dictionaries or dictionaries + locks. We will access");
                Console.WriteLine("those dictionaries from many threads (ProcessorCount threads*2).");
                Console.WriteLine("In this test the multi-threaded dictionaries should be the winners,");
                Console.WriteLine("usually having very near performance values, while the");
                Console.WriteLine("Normal dictionaries should be ordered from the fastest to the slowest as:");
                Console.WriteLine("SpinReaderWriterLockSlim (my lock), full lock and .Net ReaderWriterLockSlim.");
                Console.WriteLine("Note that the dictionaries are already filled, so it will be no parallel");
                Console.WriteLine("writes. Only parallel reads, and differences on the time of dictionaries");
                Console.WriteLine("that create values in parallel or not are simple luck.");
                Console.WriteLine();

                allSamples.Run(Environment.ProcessorCount * 2, _FastForEach);
                allSamples = null;

                Console.WriteLine("Press enter to execute the fourth test.");
                Console.ReadLine();

                Console.Clear();
                Console.WriteLine("Now we will recreate the dictionaries. So, we will execute many threads");
                Console.WriteLine("in parallel, but the fastest threads will not find a value there");
                Console.WriteLine("and will create them. Other threads will use those created values.");
                Console.WriteLine("Here we will see the difference of creating values in parallel or not.");
                Console.WriteLine();

                allSamples = new AllSamples(true, _FastResultCreator);
                allSamples.Run(Environment.ProcessorCount * 2, _FastForEach);
                allSamples = null;

                Console.WriteLine("Press enter to execute the fifth test.");
                Console.ReadLine();

                Console.Clear();
                Console.WriteLine("Until now we had one kind of extreme situations. All threads were getting");
                Console.WriteLine("or creating the same values at the same time.");
                Console.WriteLine("But what about threads creating different values and putting them");
                Console.WriteLine("at the same time into the dictionary?");
                Console.WriteLine("This is where I believed ConcurrentDictionaries will do much");
                Console.WriteLine("better, but the reality is: They didn't. They are the worst.");
                Console.WriteLine("But wait for some explanations on the next test.");
                Console.WriteLine();

                allSamples = new AllSamples(true, _FastResultCreator);
                allSamples.Run(Environment.ProcessorCount * 2, _FastNonCollidingForEach);
                allSamples = null;

                Console.WriteLine("Press enter to see the sixth test.");
                Console.ReadLine();

                _WaitTenMilliseconds();
                Console.Clear();
                Console.WriteLine("Finally we will have a little reality here (only a little).");
                Console.WriteLine("Our create values until now where really fast. Instantaneous.");
                Console.WriteLine("Why would we use a dictionary to cache results if we can call the");
                Console.WriteLine("delegate that creates the value directly and it will be faster?");
                Console.WriteLine("Ok, there are some cases (like singletons) that you may need, but");
                Console.WriteLine("one of the biggest points of dictionaries is to store data that is");
                Console.WriteLine("slow to create. So, let's create a slow creator. It takes 3 milliseconds");
                Console.WriteLine(" to do its work. That means: " + _iterationsFor3Milliseconds + " unused iterations.");
                Console.WriteLine();

                allSamples = new AllSamples(true, _SlowResultCreator);
                allSamples.Run(_COUNT_MANY_THREADS, _SlowNonCollidingForEach);
                allSamples = null;

                Console.WriteLine("Press enter to go to the final test.");
                Console.ReadLine();

                Console.Clear();
                Console.WriteLine("Now we will have a mix. All the creations will be slow, but some threads");
                Console.WriteLine("will be adding different values while others may be trying to get or create");
                Console.WriteLine("the same values in parallel.");
                Console.WriteLine();

                allSamples = new AllSamples(true, _SlowResultCreator);
                allSamples.Run(_COUNT_MANY_THREADS, _SlowSomeCollisionsForEach);
                allSamples = null;

                Console.WriteLine("Press enter to restart the tests.");
                Console.ReadLine();

                Console.Clear();
                Console.WriteLine("I lied to you. We will not restart the tests yet.");
                Console.WriteLine("But if you really want to do it, it is better. The tests at");
                Console.WriteLine("the second execution usually have a difference, that starts");
                Console.WriteLine("to become a constant. That is, the more you use it, the");
                Console.WriteLine("the results will be nearer the last result.");
                Console.WriteLine();
                Console.WriteLine("My personal conclusion is that normal dictionaries are the fastest");
                Console.WriteLine("ones for insertion. If you can get many values, use a single lock and add");
                Console.WriteLine("them into the dictionary, do it. It is safe and faster than any");
                Console.WriteLine("concurrent alternative.");
                Console.WriteLine();
                Console.WriteLine("But if you need to write from many threads, well, think about");
                Console.WriteLine("probability and constraints. I usually write only a little");
                Console.WriteLine("and read a lot into dictionaries. So, the fastest reader, the better.");
                Console.WriteLine();
                Console.WriteLine("Now, I will stop talking. Press enter to restart the tests.");
                Console.ReadLine();
            }
        }