Beispiel #1
0
        static void Main(string[] args)
        {
            const int sleepDurationInSeconds = 1000;

            // TaskFactory.StartNew() vs. Task.Run()
            ActionTimer.Time("TaskFactory.StartNew()", () =>
            {
                Task factoryTask = Task.Factory.StartNew(() => Task.Delay(sleepDurationInSeconds));
                Task.WaitAll(factoryTask);
            });

            ActionTimer.Time("Task.Run()", () =>
            {
                Task runTask = Task.Run(() => Task.Delay(sleepDurationInSeconds));
                Task.WaitAll(runTask);
            });

            // Disclaimer
            Console.WriteLine(Environment.NewLine + "Disclaimer:" + Environment.NewLine + "TaskFactory.StartNew() runs faster because Task.Run goes through a setup process for async/await. The task returned by TaskFactory.StartNew can not be used with async/await unless unwraped into an asynchronous operation with TaskExtensions.Unwrap()." + Environment.NewLine);

            // Task Cancellation
            ActionTimer.Time("Task Cancellation", () =>
            {
                Console.WriteLine("Starting cancellable task which will run for 60 seconds if not cancelled (cancellation is set to occur after 3 seconds).");
                CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
                Task cancelableTask = Pseudo.LongRunningCancellableTask(cancellationTokenSource.Token);
                cancellationTokenSource.CancelAfter(3000);
                cancelableTask.Wait();
            });

            // Async / Await
            AsyncAwaitConcepts();

            Console.ReadLine();
        }
Beispiel #2
0
        public void ExploratoryTesting_OnPerformance()
        {
            var watch = new Stopwatch();

            ActionTimer.Time(watch, () =>
            {
                var c = new WithoutEnsure().NonZero;
            },
                             1000000);
            long withoutEnsure = watch.ElapsedTicks;

            Debug.WriteLine("withoutEnsure: " + withoutEnsure);

            watch.Reset();
            ActionTimer.Time(watch, () =>
            {
                var c = new WithEnsure().NonZero;
            },
                             1000000);
            long withEnsure = watch.ElapsedTicks;

            Debug.WriteLine("withEnsure: " + withEnsure);

            watch.Reset();
            ActionTimer.Time(watch, () =>
            {
                var c = new WithNullable().NonZero;
            }, 1000000);
            long withNullable = watch.ElapsedTicks;

            Debug.WriteLine("withNullable: " + withNullable);

            Assert.That(withoutEnsure, Is.LessThan(withEnsure).And.LessThan(withNullable),
                        "doing nothing is the fastest, but it does allow a undefined value in the enumeration.");
            Assert.That(withEnsure, Is.GreaterThan(withNullable),
                        "having a custom method to ensure the defined value is more expensive than using a nullable private field");
        }
Beispiel #3
0
        public void MultipleCallsToInitializer_AreFasterThan_MultipleCallsToProvider()
        {
            var      provider     = new EmbeddedXmlProvider();
            TimeSpan providerTime = ActionTimer.Time(() =>
            {
                foreach (var code in Enumeration.GetValues <CurrencyIsoCode>())
                {
                    provider.Get(code);
                }
            });

            TimeSpan initializerTime = ActionTimer.Time(() =>
            {
                using (var initializer = new EmbeddedXmlInitializer())
                {
                    foreach (var code in Enumeration.GetValues <CurrencyIsoCode>())
                    {
                        initializer.Get(code);
                    }
                }
            });

            Assert.That(initializerTime, Is.LessThan(providerTime));
        }
Beispiel #4
0
        static void Main(string[] args)
        {
            // Setup
            int       value      = 0;
            const int oneBillion = 1000000000;

            // Without "lock" synchronization
            Console.WriteLine("Counting to 1,000,000,000 without locking...");

            ActionTimer.Time("Without \"lock\"", () =>
            {
                Task withoutLockTaskA = Task.Run(() =>
                {
                    while (value < oneBillion)
                    {
                        value++;
                    }
                });

                Task withoutLockTaskB = Task.Run(() =>
                {
                    while (value < oneBillion)
                    {
                        Thread.Sleep(1);
                        value++;
                    }
                });

                Task.WaitAll(withoutLockTaskA, withoutLockTaskB);
            }, false);

            Console.WriteLine("Computed value: " + value.ToString("N0"));
            Console.WriteLine(value != oneBillion ? "(Incorrect value was produced due to race conditions)" : "(Correct value was produced... Try running it again)");
            Console.WriteLine();

            // Keyword: "lock" synchronization
            Console.WriteLine("Counting to 1,000,000,000 using keyword \"lock\" for synchronization...");
            value = 0;
            object keywordLockObject = new object();

            ActionTimer.Time("Keyword \"lock\" synchronization", () =>
            {
                Task withLockTaskA = Task.Run(() =>
                {
                    while (true)
                    {
                        lock (keywordLockObject)
                        {
                            if (value < oneBillion)
                            {
                                value++;
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                });

                Task withLockTaskB = Task.Run(() =>
                {
                    while (true)
                    {
                        Thread.Sleep(1);

                        lock (keywordLockObject)
                        {
                            if (value < oneBillion)
                            {
                                value++;
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                });

                Task.WaitAll(withLockTaskA, withLockTaskB);
            }, false);

            Console.WriteLine("Computed value: " + value.ToString("N0"));
            Console.WriteLine(value != oneBillion ? "(Incorrect value was produced due to race conditions) [This message will never show]" : "(Correct value was produced)");
            Console.WriteLine();

            // Monitor equivalent of "lock" keyword
            Console.WriteLine("Counting to 1,000,000,000 using a monitor (lock equivalent) for synchronization.");
            value = 0;
            object monitorLockObject = new object();

            ActionTimer.Time("Monitor equivalent of \"lock\" keyword", () =>
            {
                Task withMonitorTaskA = Task.Run(() =>
                {
                    while (true)
                    {
                        bool lockTaken = false;
                        try
                        {
                            Monitor.Enter(monitorLockObject, ref lockTaken);

                            if (value < oneBillion)
                            {
                                value++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        finally
                        {
                            if (lockTaken)
                            {
                                Monitor.Exit(monitorLockObject);
                            }
                        }
                    }
                });

                Task withMonitorTaskB = Task.Run(() =>
                {
                    while (true)
                    {
                        Thread.Sleep(1);

                        bool lockTaken = false;
                        try
                        {
                            Monitor.Enter(monitorLockObject, ref lockTaken);

                            if (value < oneBillion)
                            {
                                value++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        finally
                        {
                            if (lockTaken)
                            {
                                Monitor.Exit(monitorLockObject);
                            }
                        }
                    }
                });

                Task.WaitAll(withMonitorTaskA, withMonitorTaskB);
            });

            Console.WriteLine("Computed value: " + value.ToString("N0"));
            Console.WriteLine(value != oneBillion ? "(Incorrect value was produced due to race conditions) [This message will never show]" : "(Correct value was produced)");
            Console.WriteLine();

            Console.ReadLine();
        }
        static void Main(string[] args)
        {
            // Setup
            int iterations = 10;

            Console.WriteLine("Starting... ");

            // Non-Parallel
            ActionTimer.Time("Non-Parallel", () =>
            {
                for (int i = 0; i < iterations; i++)
                {
                    Pseudo.LongRunningAction().Invoke();
                }
            });

            // Parallel.For
            ActionTimer.Time("Parallel.For", () => Parallel.For(0, iterations, Pseudo.LongRunningActionInt()));

            // Parallel.Foreach
            ActionTimer.Time("Parallel.ForEach", () => Parallel.ForEach(Enumerable.Range(0, iterations), Pseudo.LongRunningActionInt()));

            // Parallel.Invoke
            Action[] iterationActions = new Action[iterations];
            for (int i = 0; i < iterationActions.Length; i++)
            {
                iterationActions[i] = Pseudo.LongRunningAction();
            }

            ActionTimer.Time("Parallel.Invoke", () => Parallel.Invoke(iterationActions));

            // Other Parallel method overloads
            ActionTimer.Time("Parallel.Foreach overload using the TLocal variable and TLocal finalizer (time has significance for this example)", () =>
            {
                const int maxRange = 100000;
                int totalBytes     = 0;
                Random random      = new Random();
                Parallel.ForEach(Enumerable.Range(0, random.Next(maxRange / 2, maxRange)), () => 0,
                                 (integer, loopState, threadLocalSubtotal) =>
                {
                    return(threadLocalSubtotal + BitConverter.GetBytes(integer).Length);
                },
                                 (threadLocalSubtotal) =>
                {
                    Interlocked.Add(ref totalBytes, threadLocalSubtotal);
                });
            });


            ActionTimer.Time("Parallel.Invoke", () => Parallel.Invoke(iterationActions));

            // P-LINQ Setup
            iterations = 100000;
            List <int> dataSet = Enumerable.Range(1, iterations).ToList();

            // LINQ (Non-Parallelized) Method Syntax
            ActionTimer.Time("LINQ (Non-Parallelized) Method Syntax", () => dataSet.Where(value => value % 2 == 0).ToList());

            // LINQ (Non-Parallelized) Query Syntax
            ActionTimer.Time("LINQ (Non-Parallelized) Query Syntax", () =>
            {
                (from value in dataSet
                 where value % 2 == 0
                 select value).ToList();
            });

            // P-LINQ Method Syntax
            ActionTimer.Time("P-LINQ Method Syntax", () => dataSet.AsParallel().Where(value => value % 2 == 0).ToList());

            // P-LINQ Query Syntax
            ActionTimer.Time("P-LINQ Query Syntax", () =>
                             (from value in dataSet.AsParallel()
                              where value % 2 == 0
                              select value).ToList()
                             );

            // LINQ ForEach
            ActionTimer.Time("LINQ ForEach", () => dataSet.ForEach((value) => { value = value / 2; }));

            // P-LINQ ForAll
            ActionTimer.Time("P-LINQ ForAll", () => dataSet.AsParallel().ForAll((value) => { value = value / 2; }));

            // Disclaimer
            Console.WriteLine(Environment.NewLine + "Disclaimer:" + Environment.NewLine + "Subsequent Parallel method calls may run faster due to memory caching.");

            Console.ReadLine();
        }
        static void Main(string[] args)
        {
            // NOTE: The "ToList()" calls below are intentional for to immediately execute the otherwise deffered execution of the query for the sake of being able to use the "ForEach" extension of the IEnumerable interface to reduce output code.

            // Setup
            List <Pseudo.StateCityData> pseudoData      = Pseudo.GetPseudoStateCityData();
            List <Pseudo.CityData>      pseudoCityData  = Pseudo.GetPseudoCityData();
            List <Pseudo.StateData>     pseudoStateData = Pseudo.GetPseudoStateData();

            Console.WriteLine("Pseudo Data:");
            pseudoData.ForEach(data => Console.WriteLine(data.State + " " + data.City));
            Console.WriteLine();

            // SelectMany
            Console.WriteLine("SelectMany Method:");
            byte[] allCityBytes = pseudoData.SelectMany(data => Encoding.UTF8.GetBytes(data.City)).ToArray();
            Console.WriteLine(Encoding.UTF8.GetString(allCityBytes));
            Console.WriteLine();

            // Projection Example 1 - Method Syntax
            Console.WriteLine("Projected City Data - Method Syntax:");
            var pseudoCityDataCollection = pseudoData.Select(data => data.City);

            pseudoCityDataCollection.ToList().ForEach(cityData => Console.WriteLine(cityData));
            Console.WriteLine();

            // Projection Example 1 - Query Syntax
            Console.WriteLine("Projected City Data - Query Syntax:");
            var pseudoCityDataQuerySyntax = (from data in pseudoData select data.City);

            pseudoCityDataQuerySyntax.ToList().ForEach(cityData => Console.WriteLine(cityData));
            Console.WriteLine();

            // Projection Example 2 - Method Syntax (Anonymous Type Projection)
            Console.WriteLine("Projected Anonymous State & City Data - Method Syntax:");
            var pseudoStateCityDataCollection = pseudoData.Select(data => new { CityAndState = data.City + ", " + data.State });

            pseudoStateCityDataCollection.ToList().ForEach(data => Console.WriteLine(data.CityAndState));
            Console.WriteLine();

            // Projection Example 2 - Query Syntax (Anonymous Type Projection)
            Console.WriteLine("Projected Anonymous State & City Data - Query Syntax:");
            var pseudoStateCityDataCollectionQuerySyntax = (from data in pseudoData select new { CityAndState = data.City + ", " + data.State });

            pseudoStateCityDataCollectionQuerySyntax.ToList().ForEach(data => Console.WriteLine(data.CityAndState));
            Console.WriteLine();

            // Orderby Clause - Method Syntax
            Console.WriteLine("OrderBy - Method Syntax:");
            var pseudoOrderByCity = pseudoData.OrderBy(data => data.City).Select(data => data.City);

            pseudoOrderByCity.ToList().ForEach(data => Console.WriteLine(data));
            Console.WriteLine();

            // Orderby Clause - Query Syntax
            Console.WriteLine("OrderBy - Query Syntax:");
            var pseudoOrderByCityQuerySyntax = from data in pseudoData orderby data.City ascending select data.City;

            pseudoOrderByCityQuerySyntax.ToList().ForEach(data => Console.WriteLine(data));
            Console.WriteLine();

            // Group Clause - Method Syntax
            Console.WriteLine("Group - Method Syntax:");
            var pseudoCityStateGroup = pseudoData.GroupBy(data => data.City[0]);

            pseudoCityStateGroup.ToList().ForEach(displayGroupData);

            // Group Clause - Query Syntax
            Console.WriteLine("Group - Query Syntax:");
            var pseudoCityStateGroupQuerySyntax = from data in pseudoData group data by data.City[0];

            pseudoCityStateGroupQuerySyntax.ToList().ForEach(displayGroupData);

            // Join Clause - Method Syntax
            Console.WriteLine("Join - Method Syntax:");
            var pseudoCityStateJoin = pseudoCityData.Join(pseudoStateData, cityData => cityData.StateId, stateData => stateData.StateId, (cityData, stateData) => new { CityAndState = cityData.City + ", " + stateData.State });

            pseudoCityStateJoin.ToList().ForEach(data => Console.WriteLine(data.CityAndState));
            Console.WriteLine();

            // Join Clause - Query Syntax
            Console.WriteLine("Join - Query Syntax:");
            var pseudoCityStateJoinQuerySyntax = from cityData in pseudoCityData
                                                 join stateData in pseudoStateData on cityData.StateId equals stateData.StateId
                                                 select new { CityAndState = cityData.City + ", " + stateData.State };

            pseudoCityStateJoinQuerySyntax.ToList().ForEach(data => Console.WriteLine(data.CityAndState));
            Console.WriteLine();

            // Let Clause
            // NOTE: Could just write "from data in pseudoData select cityInReverse"... "Let" is more useful when the result needs to be used in a subsequent "from" clauses (i.e. from using String.Split()).
            Console.WriteLine("Let Clause - Cities in Reverse:");
            var letClauseQuery = from data in pseudoData
                                 let cityInReverse = data.City.Reverse()
                                                     select cityInReverse;

            letClauseQuery.ToList().ForEach(cityInReverse => Console.WriteLine(cityInReverse.ToArray()));
            Console.WriteLine();

            // Deffered Query Execution
            int iterations = 100000;

            Console.WriteLine("Deffered Query Execution - Query does not execute until it is enumerated:");
            ActionTimer.Time("Declaring The Query", () =>
            {
                for (int i = 0; i < iterations; i++)
                {
                    var defferedExecutionAnonymousScope = from data in pseudoData group data by data.City into g orderby g.Key ascending select g;
                }
            });

            var defferedExecution = from data in pseudoData
                                    group data by data.City into g
                                    orderby g.Key ascending
                                    select g;

            ActionTimer.Time("Executing the Query", () =>
            {
                for (int i = 0; i < iterations; i++)
                {
                    // NOTE: Compiler might optimize this out... If it does, save it to a non-anonymously scoped List<IGrouping<string, Pseudo.StateCityData>> variable and display it so the enumeration is actually used.
                    defferedExecution.ToList();
                }
            });

            Console.ReadLine();
        }