Beispiel #1
0
 public static void Main(string[] args)
 {
     try
     {
         BenchController.Run(args);
     }
     catch (Exception ex)
     {
         BencherUtils.DisplayException(ex);
     }
 }
Beispiel #2
0
        private static void WarmupDB()
        {
            IBencher dbWarmer = new DataTableBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            };

            Console.WriteLine("\nWarming up DB, DB client code and CLR");
            Console.WriteLine("====================================================================");
            BenchController.DisplayBencherInfo(dbWarmer);
            for (int i = 0; i < LoopAmount; i++)
            {
                var result = dbWarmer.PerformSetBenchmark();
                BenchController.ReportSetResult(result);
            }
        }
Beispiel #3
0
        private static void DisplayHeader()
        {
            bool releaseBuild = true;

#if DEBUG
            releaseBuild = false;
#endif
            var    conBuilder       = new SqlConnectionStringBuilder(ConnectionString);
            string sqlServerVersion = "Unknown";
            using (var conForHeader = new SqlConnection(ConnectionString))
            {
                conForHeader.Open();
                sqlServerVersion = conForHeader.ServerVersion;
                conForHeader.Close();
            }

            Console.WriteLine("+-------------------------------------------------------------------------------------------");
            Console.WriteLine("| Raw Data Access / ORM Benchmarks.");
            Console.WriteLine(@"| Code available at              : https://github.com/FransBouma/RawDataAccessBencher");
            Console.WriteLine("| Benchmarks run on              : {0}", DateTime.Now.ToString("F"));
            Console.WriteLine("| Registered benchmarks          :");
            foreach (var bencher in RegisteredBenchers)
            {
                BenchController.DisplayBencherInfo(bencher, "| \t", suffixWithDashLine: false);
            }
            Console.WriteLine("| Run set benchmarks             : {0}", PerformSetBenchmarks);
            Console.WriteLine("| Run individual fetch benchmarks: {0}", PerformIndividualBenchMarks);
            Console.WriteLine("| Number of set fetches          : {0}", LoopAmount);
            Console.WriteLine("| Number of individual keys      : {0}", IndividualKeysAmount);
            Console.WriteLine("| Release build                  : {0}", releaseBuild);
            Console.WriteLine("| Client OS                      : {0} ({1}bit)", Environment.OSVersion, Environment.Is64BitOperatingSystem ? "64" : "32");
            Console.WriteLine("| Bencher runs as 64bit          : {0}", Environment.Is64BitProcess);
#if NETCOREAPP
            Console.WriteLine("| .NET Type                      : .NET Core");
            Console.WriteLine("| CLR version                    : {0} {1}", PlatformServices.Default.Application.RuntimeFramework.Identifier,
                              PlatformServices.Default.Application.RuntimeFramework.Version);
#else
            Console.WriteLine("| .NET Type                      : .NET Full");
            Console.WriteLine("| CLR version                    : {0}", Environment.Version);
#endif
            Console.WriteLine("| Number of CPUs                 : {0}", Environment.ProcessorCount);
            Console.WriteLine("| Server used                    : {0}", conBuilder.DataSource);
            Console.WriteLine("| Catalog used                   : {0}", conBuilder.InitialCatalog);
            Console.WriteLine("| SQL Server version used        : {0}", sqlServerVersion);
            Console.WriteLine("+-------------------------------------------------------------------------------------------\n");
        }
Beispiel #4
0
        private static void RunRegisteredBenchers()
        {
            Console.WriteLine("\nStarting benchmarks.");
            Console.WriteLine("====================================================================");

            foreach (var bencher in RegisteredBenchers)
            {
                BenchController.DisplayBencherInfo(bencher);
                try
                {
                    BenchController.RunBencher(bencher);
                }
                catch (Exception ex)
                {
                    BencherUtils.DisplayException(ex);
                }
            }

            Console.WriteLine("\nPerforming memory measurement runs.");
            Console.WriteLine("====================================================================");
#if !NETCOREAPP
            AppDomain.MonitoringIsEnabled = true;
#endif
            foreach (var bencher in RegisteredBenchers)
            {
                BenchController.DisplayBencherInfo(bencher);
                bencher.CollectMemoryAllocated = true;
                try
                {
                    BenchController.RunMemoryAnalysisForBencher(bencher);
                }
                catch (Exception ex)
                {
                    BencherUtils.DisplayException(ex);
                }

                bencher.CollectMemoryAllocated = false;
            }
        }
Beispiel #5
0
 private static void DisplayBencherInfo(IBencher bencher)
 {
     BenchController.DisplayBencherInfo(bencher, "\n", suffixWithDashLine: true);
 }
Beispiel #6
0
        public static void Run(string[] args)
        {
            bool autoExit = false;

            if (args.Length > 0)
            {
                autoExit = args[0] == "/a";
            }
            BenchController.InitConnectionString();

            CacheController.RegisterCache(ConnectionString, new ResultsetCache());
            RegisteredBenchers.Add(new HandCodedBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new HandCodedBencherUsingGetFieldValue()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new RepoDbRawSqlBencher()
            {
                ConnectionStringToUse = ConnectionString, CommandText = SqlSelectCommandText
            });
            RegisteredBenchers.Add(new RepoDbPocoBencher()
            {
                ConnectionStringToUse = ConnectionString, CommandText = SqlSelectCommandText
            });
            RegisteredBenchers.Add(new HandCodedBencherUsingBoxing()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new HandCodedBencherUsingBoxingGetValue()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new RawDbDataReaderBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new NPocoBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new LINQ2DBCompiledBencher(ConnectionString));
            RegisteredBenchers.Add(new LINQ2DBNormalBencher(ConnectionString));
            RegisteredBenchers.Add(new LLBLGenProNoChangeTrackingRawSQLPocoBencher(ConnectionString)
            {
                CommandText = SqlSelectCommandText
            });
            RegisteredBenchers.Add(new LLBLGenProNoChangeTrackingQuerySpecPocoBencher(ConnectionString));
            RegisteredBenchers.Add(new LLBLGenProNoChangeTrackingLinqPocoBencher(ConnectionString));
            RegisteredBenchers.Add(new LLBLGenProNoChangeTrackingBencher(ConnectionString));
            RegisteredBenchers.Add(new LLBLGenProResultsetCachingBencher(ConnectionString));
            RegisteredBenchers.Add(new LLBLGenProNormalBencher(ConnectionString));
            RegisteredBenchers.Add(new LLBLGenProDTOBencher(ConnectionString));
            RegisteredBenchers.Add(new DapperBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new ChainBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new OrmLiteBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new DataTableBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new ChainCompiledBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });

#if NETCOREAPP
            // EF Core 3.x does support netstandard 2.0 but the benchers fail to build on .NET 4.8 so we'll skip them on netfx
            RegisteredBenchers.Add(new EntityFrameworkCoreNoChangeTrackingBencher()
            {
                ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new EntityFrameworkCoreNormalBencher()
            {
                ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new EntityFrameworkCoreDTOBencher()
            {
                ConnectionStringToUse = ConnectionString
            });
#else
            RegisteredBenchers.Add(new MassiveBencher());
            RegisteredBenchers.Add(new NHibernateNormalBencher());
            RegisteredBenchers.Add(new LinqToSqlNoChangeTrackingBencher());
            RegisteredBenchers.Add(new LinqToSqlNormalBencher());
            RegisteredBenchers.Add(new EntityFrameworkNoChangeTrackingBencher());
            RegisteredBenchers.Add(new EntityFrameworkNormalBencher());
            RegisteredBenchers.Add(new PetaPocoBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
            RegisteredBenchers.Add(new PetaPocoFastBencher()
            {
                CommandText = SqlSelectCommandText, ConnectionStringToUse = ConnectionString
            });
#endif
            BenchController.DisplayHeader();
            BenchController.WarmupDB();
            BenchController.FetchKeysForIndividualFetches();

            // Uncomment the line below if you want to profile a bencher. Specify the bencher instance and follow the guides on the screen.
            //ProfileBenchers(RegisteredBenchers.FirstOrDefault(b => b.GetType() == typeof(LINQ2DBNormalBencher)));
            BenchController.RunRegisteredBenchers();
            BenchController.ReportResultStatistics(autoExit);
        }
Beispiel #7
0
        private static void RunBencher(IBencher bencher)
        {
            bencher.ResetResults();
            Console.WriteLine("First one warm-up run of each bench type to initialize constructs. Results will not be collected.");
            BenchResult result = null;

            if (PerformSetBenchmarks && bencher.SupportsSetFetch)
            {
                result = bencher.PerformSetBenchmark(discardResults: true);
                BenchController.ReportSetResult(result);
            }
            if (bencher.SupportsEagerLoading)
            {
                result = bencher.PerformEagerLoadBenchmark(discardResults: true);
                BenchController.ReportEagerLoadResult(result);
                if (PerformAsyncBenchmarks && bencher.SupportsAsync)
                {
                    result = bencher.PerformAsyncEagerLoadBenchmark(discardResults: true);
                    BenchController.ReportEagerLoadResult(result);
                }
            }
            if (PerformIndividualBenchMarks && bencher.SupportsIndividualFetch)
            {
                result = bencher.PerformIndividualBenchMark(KeysForIndividualFetches, discardResults: true);
                BenchController.ReportIndividualResult(result);
            }

            if (PerformSetInsertBenchmarks && bencher.SupportsInserts)
            {
                result = bencher.PerformInsertSetBenchmark(InsertSetSize, InsertBatchSizeDefault, discardResults: true);
                BenchController.ReportInsertSetResult(result);
            }

            Console.WriteLine("Doing a GC collect...");
            BenchController.ForceGCCollect();
            Console.WriteLine("Done.");

            Console.WriteLine("\nStarting bench runs...");
            if (PerformSetBenchmarks && bencher.SupportsSetFetch)
            {
                // set benches
                Console.WriteLine("Set fetches");
                Console.WriteLine("-------------------------");
                for (int i = 0; i < LoopAmount; i++)
                {
                    result = bencher.PerformSetBenchmark();
                    BenchController.ReportSetResult(result);

                    // avoid having the GC collect in the middle of a run.
                    BenchController.ForceGCCollect();
                }
            }
            if (PerformIndividualBenchMarks && bencher.SupportsIndividualFetch)
            {
                // individual benches
                Console.WriteLine("\nSingle element fetches");
                Console.WriteLine("-------------------------");
                for (int i = 0; i < LoopAmount; i++)
                {
                    result = bencher.PerformIndividualBenchMark(KeysForIndividualFetches);
                    BenchController.ReportIndividualResult(result);

                    // avoid having the GC collect in the middle of a run.
                    BenchController.ForceGCCollect();

                    if (ApplyAntiFloodForVMUsage)
                    {
                        // sleep is to avoid hammering the network layer on the target server. If the target server is a VM, it might stall once or twice
                        // during benching, which is not what we want at it can skew the results a lot. In a very short time, a lot of queries are executed
                        // on the target server (LoopAmount * IndividualKeysAmount), which will hurt performance on VMs with very fast frameworks in some
                        // cases in some runs (so more than 2 runs are slow).
#pragma warning disable CS0162
                        Thread.Sleep(400);
#pragma warning restore CS0162
                    }
                }
            }
            if (PerformEagerLoadBenchmarks && bencher.SupportsEagerLoading)
            {
                // eager load benches
                Console.WriteLine("\nEager Load fetches");
                Console.WriteLine("-------------------------");
                for (int i = 0; i < LoopAmount; i++)
                {
                    result = bencher.PerformEagerLoadBenchmark();
                    BenchController.ReportEagerLoadResult(result);

                    // avoid having the GC collect in the middle of a run.
                    BenchController.ForceGCCollect();
                }
            }
            if (PerformAsyncBenchmarks && bencher.SupportsEagerLoading && bencher.SupportsAsync)
            {
                // eager load benches
                Console.WriteLine("\nAsync eager Load fetches");
                Console.WriteLine("-------------------------");
                for (int i = 0; i < LoopAmount; i++)
                {
                    result = bencher.PerformAsyncEagerLoadBenchmark(discardResults: false);
                    BenchController.ReportEagerLoadResult(result);

                    // avoid having the GC collect in the middle of a run.
                    BenchController.ForceGCCollect();
                }
            }
            if (PerformSetInsertBenchmarks && bencher.SupportsInserts)
            {
                // set insert benches
                Console.WriteLine("\nSet Inserts");
                Console.WriteLine("-------------------------");
                for (int i = 0; i < LoopAmount; i++)
                {
                    result = bencher.PerformInsertSetBenchmark(InsertSetSize, InsertBatchSizeDefault);
                    BenchController.ReportInsertSetResult(result);

                    // avoid having the GC collect in the middle of a run.
                    BenchController.ForceGCCollect();
                }
            }
        }
Beispiel #8
0
        private static void RunMemoryAnalysisForBencher(IBencher bencher)
        {
            Console.WriteLine("\nStarting bench runs...");
            BenchResult result;

            if (PerformSetBenchmarks && bencher.SupportsSetFetch)
            {
                // set benches
                Console.WriteLine("Set fetches");
                Console.WriteLine("-------------------------");
                result = bencher.PerformSetBenchmark(discardResults: true);
                BenchController.ReportMemoryUsageSetResult(result);
                bencher.MemorySetBenchmarks = result.NumberOfBytesAllocated;
                // avoid having the GC collect in the middle of a run.
                BenchController.ForceGCCollect();
            }
            if (PerformIndividualBenchMarks && bencher.SupportsIndividualFetch)
            {
                // individual benches
                Console.WriteLine("\nSingle element fetches");
                Console.WriteLine("-------------------------");
                result = bencher.PerformIndividualBenchMark(KeysForIndividualFetches, discardResults: true);
                BenchController.ReportMemoryUsageIndividualResult(result);
                bencher.MemoryIndividualBenchmarks = result.NumberOfBytesAllocated;

                // avoid having the GC collect in the middle of a run.
                BenchController.ForceGCCollect();

                if (ApplyAntiFloodForVMUsage)
                {
                    // sleep is to avoid hammering the network layer on the target server. If the target server is a VM, it might stall once or twice
                    // during benching, which is not what we want at it can skew the results a lot. In a very short time, a lot of queries are executed
                    // on the target server (LoopAmount * IndividualKeysAmount), which will hurt performance on VMs with very fast frameworks in some
                    // cases in some runs (so more than 2 runs are slow).
#pragma warning disable CS0162
                    Thread.Sleep(400);
#pragma warning restore CS0162
                }
            }
            if (PerformEagerLoadBenchmarks && bencher.SupportsEagerLoading)
            {
                // eager load benches
                Console.WriteLine("\nEager Load fetches");
                Console.WriteLine("-------------------------");
                result = bencher.PerformEagerLoadBenchmark(discardResults: true);
                BenchController.ReportMemoryUsageEagerLoadResult(result);
                bencher.MemoryEagerLoadBenchmarks = result.NumberOfBytesAllocated;

                // avoid having the GC collect in the middle of a run.
                BenchController.ForceGCCollect();
            }
            if (PerformAsyncBenchmarks && bencher.SupportsEagerLoading && bencher.SupportsAsync)
            {
                // eager load benches
                Console.WriteLine("\nAsync eager Load fetches");
                Console.WriteLine("-------------------------");
                result = bencher.PerformAsyncEagerLoadBenchmark(discardResults: true);
                BenchController.ReportMemoryUsageEagerLoadResult(result);
                bencher.MemoryAsyncEagerLoadBenchmarks = result.NumberOfBytesAllocated;

                // avoid having the GC collect in the middle of a run.
                BenchController.ForceGCCollect();
            }

            if (PerformSetInsertBenchmarks && bencher.SupportsInserts)
            {
                // set inserts
                Console.WriteLine("\nSet inserts");
                Console.WriteLine("-------------------------");
                result = bencher.PerformInsertSetBenchmark(InsertSetSize, InsertBatchSizeDefault, discardResults: true);
                BenchController.ReportMemoryUsageInsertSetResult(result);
                bencher.MemorySetInsertBenchmarks = result.NumberOfBytesAllocated;
                // avoid having the GC collect in the middle of a run.
                BenchController.ForceGCCollect();
            }
        }