static void OutputResults(object sender, BenchmarkOptions benchmarkOptions, RecordReaderBenchmarkArguments benchmarkArgs, long iterationIndex, BenchmarkResult result) { var fi = new System.IO.FileInfo(benchmarkArgs.Path); decimal rate = ((decimal) fi.Length / 1024 / 1024) / ((decimal) result.Timer.ElapsedMilliseconds / 1000); Console.WriteLine("{0}: {1,25}: {2,10} ticks, {3,10} bytes, {4,4} gc0, {5,4} gc1, {6,4} gc2, {7,6:F} MB/s", iterationIndex, result.Name, result.Timer.ElapsedTicks, result.UsedMemory, result.GC0, result.GC1, result.GC2, rate); Trace.WriteLine(string.Format("{0},{1},{2},{3},{4},{5},{6},{7:F}", iterationIndex, result.Name, result.Timer.ElapsedTicks, result.UsedMemory, result.GC0, result.GC1, result.GC2, rate)); }
//TODO: for now, the main program code is very tied to IO benchmarks. Needs to refactor to make it more modular. static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); var benchmarkOptions = new BenchmarkOptions { ActionIterationCount = 1, BenchmarkIterationCount = 3, ConcurrencyLevel = 1 }; var tests = BenchmarkTests.All; bool profiling = false; var converter = new StringValueConverter(); if (args.Length > 0) { tests = (BenchmarkTests) converter.ConvertTo(args[0], TrimmingOptions.Both, typeof(BenchmarkTests), BenchmarkTests.All); if (args.Length > 1) benchmarkOptions.BenchmarkIterationCount = converter.ConvertToInt64(args[1], TrimmingOptions.Both, benchmarkOptions.BenchmarkIterationCount, null); if (args.Length > 2) profiling = converter.ConvertToBoolean(args[2], TrimmingOptions.Both, false, null); } #region FixedWidthReader if (tests.HasFlag(BenchmarkTests.FixedWidthReader)) { var files = profiling ? new string[] { @"IO\Text\files\fixed.txt" } : new string[] { @"IO\Text\files\fixed.txt", @"IO\Text\files\test1.csv", @"IO\Text\files\test2.csv" }; foreach (var file in files) { Console.WriteLine("--- FixedWidthReader - {0} ---", file); var benchmarkArgs = new FixedRecordReaderBenchmarkArguments(); benchmarkArgs.Path = file; Benchmark.Execute("NLight", benchmarkOptions, benchmarkArgs, OutputResults, FixedRecordReaderBenchmarks.ReadAll); Benchmark.Execute("DataStreams", benchmarkOptions, benchmarkArgs, OutputResults, FixedRecordReaderBenchmarks.ReadAll_DataStreams); } } #endregion #region DelimitedReader if (tests.HasFlag(BenchmarkTests.DelimitedReader)) { var files = profiling ? new string[] { @"IO\Text\files\test1.csv" } : new string[] { @"IO\Text\files\test1.csv", @"IO\Text\files\test2.csv", @"IO\Text\files\test3.csv", @"IO\Text\files\test4.csv", @"IO\Text\files\test5.csv" }; foreach (var file in files) { Console.WriteLine("--- DelimitedReader - {0} ---", file); var benchmarkArgs = new DelimitedRecordReaderBenchmarkArguments(); benchmarkArgs.Path = file; benchmarkArgs.TrimWhiteSpaces = true; Benchmark.Execute("LumenWorks", benchmarkOptions, benchmarkArgs, OutputResults, DelimitedRecordReaderBenchmarks.ReadAll_LumenWorks); Benchmark.Execute("NLight", benchmarkOptions, benchmarkArgs, OutputResults, DelimitedRecordReaderBenchmarks.ReadAll); Benchmark.Execute("DataStreams", benchmarkOptions, benchmarkArgs, OutputResults, DelimitedRecordReaderBenchmarks.ReadAll_DataStreams); Benchmark.Execute("CsvHelper", benchmarkOptions, benchmarkArgs, OutputResults, DelimitedRecordReaderBenchmarks.ReadAll_CsvHelper); //Benchmark.Execute("OleDb", benchmarkOptions, benchmarkArgs, OutputResults, DelimitedRecordReaderBenchmarks.ReadAll_OleDb); //Benchmark.Execute("Regex", benchmarkOptions, benchmarkArgs, OutputResults, DelimitedRecordReaderBenchmarks.ReadAll_Regex); } } #endregion #region DelimitedReaderAdvancedEscaping if (tests.HasFlag(BenchmarkTests.DelimitedReaderAdvancedEscaping)) { var files = profiling ? new string[] { @"IO\Text\files\test4.csv" } : new string[] { @"IO\Text\files\test3.csv", @"IO\Text\files\test4.csv" }; foreach (var file in files) { Console.WriteLine("--- DelimitedReader with advanced escaping - {0} ---", file); var benchmarkArgs = new DelimitedRecordReaderBenchmarkArguments(); benchmarkArgs.Path = file; benchmarkArgs.TrimWhiteSpaces = true; benchmarkArgs.AdvancedEscapingEnabled = true; Benchmark.Execute("NLight", benchmarkOptions, benchmarkArgs, OutputResults, DelimitedRecordReaderBenchmarks.ReadAll); Benchmark.Execute("DataStreams", benchmarkOptions, benchmarkArgs, OutputResults, DelimitedRecordReaderBenchmarks.ReadAll_DataStreams); } } #endregion Console.WriteLine("\nDone"); Console.ReadLine(); }
/// <summary> /// Executes a benchmark. /// </summary> /// <typeparam name="TBenchmarkArgs">The type of class containing the benchmark arguments.</typeparam> /// <param name="benchmarkName">The name of the benchmark.</param> /// <param name="benchmarkOptions">The benchmark options.</param> /// <param name="benchmarkArgs">The benchmark arguments.</param> /// <param name="outputCallback"> /// The benchmark output callback. Its arguments are: /// <list type=""> /// <item>sender (an instance or the type of the class that executed the benchmark)</item> /// <item>benchmark options</item> /// <item>benchmark arguments</item> /// <item>current iteration index</item> /// <item>benchmark result</item> /// </list> /// </param> /// <param name="action">The operation to benchmark.</param> public static void Execute <TBenchmarkArgs>(string benchmarkName, BenchmarkOptions benchmarkOptions, TBenchmarkArgs benchmarkArgs, Action <object, BenchmarkOptions, TBenchmarkArgs, long, BenchmarkResult> outputCallback, Action <TBenchmarkArgs> action) { if (benchmarkOptions == null) { throw new ArgumentNullException(nameof(benchmarkOptions)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } benchmarkName = benchmarkName ?? string.Empty; for (long iterationIndex = 0; iterationIndex < benchmarkOptions.BenchmarkIterationCount; iterationIndex++) { GC.Collect(2, GCCollectionMode.Forced); GC.WaitForPendingFinalizers(); GC.Collect(2, GCCollectionMode.Forced); long memory = GC.GetTotalMemory(false); int gc0 = GC.CollectionCount(0); int gc1 = GC.CollectionCount(1); int gc2 = GC.CollectionCount(2); var timer = new Stopwatch(); if (benchmarkOptions.ConcurrencyLevel <= 1) { timer.Start(); for (long i = 0; i < benchmarkOptions.ActionIterationCount; i++) { Repeat(action, benchmarkArgs, benchmarkOptions.ActionRepeatCount, benchmarkOptions.CancellationToken); } timer.Stop(); } else { // total time will include overhead of multi-threading timer.Start(); Parallel.For(0, benchmarkOptions.ActionIterationCount, new ParallelOptions { CancellationToken = benchmarkOptions.CancellationToken, MaxDegreeOfParallelism = benchmarkOptions.ConcurrencyLevel }, (i) => Repeat(action, benchmarkArgs, benchmarkOptions.ActionRepeatCount, benchmarkOptions.CancellationToken)); timer.Stop(); } var result = new BenchmarkResult(); result.UsedMemory = GC.GetTotalMemory(false) - memory; result.GC0 = GC.CollectionCount(0) - gc0; result.GC1 = GC.CollectionCount(1) - gc1; result.GC2 = GC.CollectionCount(2) - gc2; result.Name = benchmarkName; result.Timer = timer; if (outputCallback != null) { object target = action.Target ?? action.Method.DeclaringType; outputCallback(target, benchmarkOptions, benchmarkArgs, iterationIndex, result); } } }