public static void Main(string[] args) { try { BenchController.Run(args); } catch (Exception ex) { BencherUtils.DisplayException(ex); } }
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); } }
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"); }
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; } }
private static void DisplayBencherInfo(IBencher bencher) { BenchController.DisplayBencherInfo(bencher, "\n", suffixWithDashLine: true); }
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); }
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(); } } }
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(); } }