From cb185269b3847905fe431b4d5a6b9aadf64d450c Mon Sep 17 00:00:00 2001 From: wei Date: Tue, 13 Jul 2021 08:29:47 +0800 Subject: [PATCH] Benchmark coderefacturing --- README.md | 2 +- README.zh-CN.md | 2 +- README.zh-Hant.md | 3 +- .../MiniExcel.Benchmarks/BenchmarkBase.cs | 36 ++ .../MiniExcel.Benchmarks/DebugConfig.cs | 91 ----- .../MiniExcel.Benchmarks.csproj | 3 + benchmarks/MiniExcel.Benchmarks/Program.cs | 348 +----------------- .../PublishProfiles/FolderProfile.pubxml | 12 + .../XlsxAsyncBenchmark.cs | 34 ++ .../MiniExcel.Benchmarks/XlsxBenchmark.cs | 259 +++++++++++++ 10 files changed, 351 insertions(+), 439 deletions(-) create mode 100644 benchmarks/MiniExcel.Benchmarks/BenchmarkBase.cs delete mode 100644 benchmarks/MiniExcel.Benchmarks/DebugConfig.cs create mode 100644 benchmarks/MiniExcel.Benchmarks/Properties/PublishProfiles/FolderProfile.pubxml create mode 100644 benchmarks/MiniExcel.Benchmarks/XlsxAsyncBenchmark.cs create mode 100644 benchmarks/MiniExcel.Benchmarks/XlsxBenchmark.cs diff --git a/README.md b/README.md index 1f16360..ae3e43d 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ IterationCount=3 LaunchCount=3 WarmupCount=3 ``` #### Import/Query Excel -Logic : (benchmarks/MiniExcel.Benchmarks/Test1%2C000%2C000x10.xlsx) as performance test basic file,A total of 10,000,000 "HelloWorld" with a file size of 23 MB +Logic : [**Test1,000,000x10.xlsx**](benchmarks/MiniExcel.Benchmarks/Test1%2C000%2C000x10.xlsx) as performance test basic file, 1,000,000 rows * 10 columns "HelloWorld" cells, 23 MB file size | Library | Method | Max Memory Usage | Mean | diff --git a/README.zh-CN.md b/README.zh-CN.md index 1dd31c6..0f0fa08 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -75,7 +75,7 @@ IterationCount=3 LaunchCount=3 WarmupCount=3 ``` #### 导入、查询 Excel 比较 -逻辑 : 以 [**Test1,000,000x10.xlsx**](benchmarks/MiniExcel.Benchmarks/Test1%2C000%2C000x10.xlsx) 做基准与主流框架做性能测试,总共 1千万笔 "HelloWorld",文件大小 23 MB +逻辑 : 以 [**Test1,000,000x10.xlsx**](benchmarks/MiniExcel.Benchmarks/Test1%2C000%2C000x10.xlsx) 做基准与主流框架做性能测试,总共 1,000,000 行 * 10 列笔 "HelloWorld",文件大小 23 MB | Library | Method | 最大内存耗用 | 平均时间 | diff --git a/README.zh-Hant.md b/README.zh-Hant.md index 706a801..2577378 100644 --- a/README.zh-Hant.md +++ b/README.zh-Hant.md @@ -71,7 +71,8 @@ IterationCount=3 LaunchCount=3 WarmupCount=3 ``` #### 導入、查詢 Excel 比較 -邏輯 : 以 [**Test1,000,000x10.xlsx**](benchmarks/MiniExcel.Benchmarks/Test1%2C000%2C000x10.xlsx) 做基準與主流框架做性能測試,總共 1千萬筆 "HelloWorld",文件大小 23 MB + +邏輯 : 以 [**Test1,000,000x10.xlsx**](benchmarks/MiniExcel.Benchmarks/Test1%2C000%2C000x10.xlsx) 做基準與主流框架做性能測試,總共 1,000,000 行 * 10 列筆 "HelloWorld",文件大小 23 MB | Library | Method | 最大記憶體耗用 | 平均時間 | diff --git a/benchmarks/MiniExcel.Benchmarks/BenchmarkBase.cs b/benchmarks/MiniExcel.Benchmarks/BenchmarkBase.cs new file mode 100644 index 0000000..7c315e4 --- /dev/null +++ b/benchmarks/MiniExcel.Benchmarks/BenchmarkBase.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Linq; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Order; + +namespace MiniExcelLibs.Benchmarks +{ + public abstract class BenchmarkBase + { + //public const string filePath = @"Test10x10.xlsx"; + //public const int rowCount = 1_0; + + public const string filePath = @"Test1,000,000x10.xlsx"; + public const int rowCount = 1_000_000; + + public IEnumerable Getvalue() + { + return Enumerable.Range(1, rowCount).Select(s => new DemoDto()); + } + + public class DemoDto + { + public string Column1 { get; set; } = "Hello World"; + public string Column2 { get; set; } = "Hello World"; + public string Column3 { get; set; } = "Hello World"; + public string Column4 { get; set; } = "Hello World"; + public string Column5 { get; set; } = "Hello World"; + public string Column6 { get; set; } = "Hello World"; + public string Column7 { get; set; } = "Hello World"; + public string Column8 { get; set; } = "Hello World"; + public string Column9 { get; set; } = "Hello World"; + public string Column10 { get; set; } = "Hello World"; + } + } +} diff --git a/benchmarks/MiniExcel.Benchmarks/DebugConfig.cs b/benchmarks/MiniExcel.Benchmarks/DebugConfig.cs deleted file mode 100644 index d676b53..0000000 --- a/benchmarks/MiniExcel.Benchmarks/DebugConfig.cs +++ /dev/null @@ -1,91 +0,0 @@ -using BenchmarkDotNet.Analysers; -using BenchmarkDotNet.Columns; -using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Diagnosers; -using BenchmarkDotNet.Exporters; -using BenchmarkDotNet.Filters; -using BenchmarkDotNet.Jobs; -using BenchmarkDotNet.Loggers; -using BenchmarkDotNet.Order; -using BenchmarkDotNet.Reports; -using BenchmarkDotNet.Toolchains.InProcess.Emit; -using BenchmarkDotNet.Validators; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; - -namespace MiniExcelLibs.Benchmarks -{ - public class DebugConfig : ManualConfig - { - public new IOrderer Orderer => DefaultOrderer.Instance; - - public new SummaryStyle SummaryStyle => SummaryStyle.Default; - - public new ConfigUnionRule UnionRule => ConfigUnionRule.Union; - - public new string ArtifactsPath => Path.Combine(Directory.GetCurrentDirectory(), "BenchmarkDotNet.Artifacts"); - - public new CultureInfo CultureInfo => null; - - public new ConfigOptions Options => ConfigOptions.KeepBenchmarkFiles | ConfigOptions.DisableOptimizationsValidator; - - public new IEnumerable GetJobs() - { - return new Job[1] - { - JobMode.Default.WithToolchain(new InProcessEmitToolchain(TimeSpan.FromHours(1.0), logOutput: true)) - }; - } - - - public new IEnumerable GetValidators() - { - return Array.Empty(); - } - - public new IEnumerable GetColumnProviders() - { - return DefaultColumnProviders.Instance; - } - - public new IEnumerable GetExporters() - { - return Array.Empty(); - } - - public new IEnumerable GetLoggers() - { - return new ILogger[1] - { - ConsoleLogger.Default - }; - } - - public new IEnumerable GetDiagnosers() - { - return Array.Empty(); - } - - public new IEnumerable GetAnalysers() - { - return Array.Empty(); - } - - public new IEnumerable GetHardwareCounters() - { - return Array.Empty(); - } - - public new IEnumerable GetFilters() - { - return Array.Empty(); - } - - public new IEnumerable GetLogicalGroupRules() - { - return Array.Empty(); - } - } -} diff --git a/benchmarks/MiniExcel.Benchmarks/MiniExcel.Benchmarks.csproj b/benchmarks/MiniExcel.Benchmarks/MiniExcel.Benchmarks.csproj index 6a8743a..f87a560 100644 --- a/benchmarks/MiniExcel.Benchmarks/MiniExcel.Benchmarks.csproj +++ b/benchmarks/MiniExcel.Benchmarks/MiniExcel.Benchmarks.csproj @@ -19,6 +19,9 @@ + + PreserveNewest + PreserveNewest diff --git a/benchmarks/MiniExcel.Benchmarks/Program.cs b/benchmarks/MiniExcel.Benchmarks/Program.cs index ed6bb51..65cd9ae 100644 --- a/benchmarks/MiniExcel.Benchmarks/Program.cs +++ b/benchmarks/MiniExcel.Benchmarks/Program.cs @@ -1,20 +1,8 @@ using System; -using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Diagnosers; -using BenchmarkDotNet.Order; using BenchmarkDotNet.Running; -using ClosedXML.Excel; -using DocumentFormat.OpenXml; -using DocumentFormat.OpenXml.Packaging; -using DocumentFormat.OpenXml.Spreadsheet; -using ExcelDataReader; using MiniExcelLibs; using OfficeOpenXml; @@ -24,342 +12,12 @@ namespace MiniExcelLibs.Benchmarks { static void Main(string[] args) { -#if !DEBUG - BenchmarkSwitcher.FromTypes(new[]{typeof(XlsxBenchmark)}).Run(args, new Config()); +#if DEBUG + new XlsxBenchmark().Epplus_QueryFirst_Test(); #else - BenchmarkSwitcher.FromTypes(new[] { typeof(XlsxBenchmark) }).Run(args, new DebugInProcessConfig() ); - //new TemplateXlsxBenchmark().MiniExcel_Template_Generate_Test(); - //new XlsxBenchmark().MiniExcelCreateTest(); + BenchmarkSwitcher.FromTypes(new[]{typeof(XlsxBenchmark)}).Run(args, new Config()); #endif Console.Read(); } } - - [BenchmarkCategory("Framework")] - [MemoryDiagnoser] - [SimpleJob(launchCount: 1, warmupCount: 1, targetCount: 1,invocationCount:1,baseline:false)] - [Orderer(SummaryOrderPolicy.FastestToSlowest)] - public abstract class BenchmarkBase - { -#if !DEBUG - public const string filePath = @"Test10,000x10.xlsx"; - public const int runCount = 1_000_000; -#else - public const string filePath = @"Test100x10.xlsx"; - public const int runCount = 10; -#endif - - //public const string filePath = @"Test10x10.xlsx"; - //public const int runCount = 10; - - public static IEnumerable GetValues() - { -#if !DEBUG - return Enumerable.Range(1, runCount).Select(s => new Demo()); -#else - return Enumerable.Range(1, runCount).Select(s => new Demo()); -#endif - } - } - - public class XlsxBenchmark: BenchmarkBase - { - [GlobalSetup] - public void SetUp() - { - ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial; - System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); - } - - [Benchmark(Description = "MiniExcel Template Generate")] - public void MiniExcel_Template_Generate_Test() - { - { - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); - const string templatePath = @"TestTemplateBasicIEmumerableFill.xlsx"; - var value = new - { - employees = Enumerable.Range(1, runCount).Select(s => new { name = "Jack", department = "HR" }) - }; - MiniExcel.SaveAsByTemplate(path, templatePath, value); - } - } - - [Benchmark(Description = "MiniExcel Async Template Generate")] - public async Task MiniExcel_Template_Generate_Async_Test() - { - { - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); - const string templatePath = @"TestTemplateBasicIEmumerableFill.xlsx"; - var value = new - { - employees = Enumerable.Range(1, runCount).Select(s => new { name = "Jack", department = "HR" }) - }; - await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value); - } - } - - [Benchmark(Description = "ClosedXml.Report Template Generate")] - public void ClosedXml_Report_Template_Generate_Test() - { - { - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); - var templatePath = @"TestTemplateBasicIEmumerableFill_ClosedXML_Report.xlsx"; - var template = new ClosedXML.Report.XLTemplate(templatePath); - var value = new - { - employees = Enumerable.Range(1, runCount).Select(s => new { name = "Jack", department = "HR" }) - }; - template.AddVariable(value); - template.Generate(); - template.SaveAs(path); - } - } - - [Benchmark(Description = "MiniExcel QueryFirst")] - public void MiniExcel_QueryFirst_Test() - { - MiniExcel.Query(filePath).First(); - } - - [Benchmark(Description = "MiniExcel Query")] - public void MiniExcel_Query() - { - foreach (var item in MiniExcel.Query(filePath)) - { - - } - } - - [Benchmark(Description = "ExcelDataReader QueryFirst")] - public void ExcelDataReader_QueryFirst_Test() - { -#if DEBUG - System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); -#endif - using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read)) - using (var reader = ExcelReaderFactory.CreateReader(stream)) - { - var d = new List(); - reader.Read(); - for (int i = 0; i < reader.FieldCount; i++) - d.Add(reader.GetValue(i)); - } - } - - [Benchmark(Description = "ExcelDataReader Query")] - public void ExcelDataReader_Query_Test() - { -#if DEBUG - System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); -#endif - using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read)) - using (var reader = ExcelReaderFactory.CreateReader(stream)) - { - while (reader.Read()) - { - var d = new List(); - for (int i = 0; i < reader.FieldCount; i++) - d.Add(reader.GetValue(i)); - } - } - } - - [Benchmark(Description = "Epplus QueryFirst")] - public void Epplus_QueryFirst_Test() - { -#if DEBUG - ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial; -#endif - using (var p = new ExcelPackage(new FileInfo(filePath))) - { - p.Workbook.Worksheets[0].Row(1); - } - } - - [Benchmark(Description = "Epplus Query")] - public void Epplus_Query_Test() - { -#if DEBUG - ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial; -#endif - // [c# - How do I iterate through rows in an excel table using epplus? - Stack Overflow](https://stackoverflow.com/questions/21742038/how-do-i-iterate-through-rows-in-an-excel-table-using-epplus) - using (var p = new ExcelPackage(new FileInfo(filePath))) - { - var workSheet = p.Workbook.Worksheets[0]; - var start = workSheet.Dimension.Start; - var end = workSheet.Dimension.End; - for (int row = start.Row; row <= end.Row; row++) - { // Row by row... - for (int col = start.Column; col <= end.Column; col++) - { // ... Cell by cell... - object cellValue = workSheet.Cells[row, col].Text; // This got me the actual value I needed. - } - } - } - } - - [Benchmark(Description = "ClosedXml QueryFirst")] - public void ClosedXml_QueryFirst_Test() - { - using (var workbook = new XLWorkbook(filePath)) - { - workbook.Worksheet(1).Row(1); - } - } - - [Benchmark(Description = "ClosedXml Query")] - public void ClosedXml_Query_Test() - { - using (var workbook = new XLWorkbook(filePath)) - { - workbook.Worksheet(1).Rows(); - } - } - - [Benchmark(Description = "OpenXmlSDK QueryFirst")] - public void OpenXmlSDK_QueryFirst_Test() - { - using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filePath, false)) - { - WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart; - WorksheetPart worksheetPart = workbookPart.WorksheetParts.First(); - SheetData sheetData = worksheetPart.Worksheet.Elements().First(); - var firstRow = sheetData.Elements().First(); - } - } - - [Benchmark(Description = "OpenXmlSDK Query")] - public void OpenXmlSDK_Query_Test() - { - using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filePath, false)) - { - WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart; - WorksheetPart worksheetPart = workbookPart.WorksheetParts.First(); - SheetData sheetData = worksheetPart.Worksheet.Elements().First(); - var firstRow = sheetData.Elements().ToList(); - } - } - - [Benchmark(Description = "MiniExcel Create Xlsx")] - public void MiniExcelCreateTest() - { - var values = GetValues(); - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); - using (var stream = File.Create(path)) - stream.SaveAs(values); - File.Delete(path); - } - - [Benchmark(Description = "MiniExcel Async Create Xlsx")] - public async Task MiniExcelCreateAsyncTest() - { - var values = GetValues(); - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); - using (var stream = File.Create(path)) - await stream.SaveAsAsync(values); - File.Delete(path); - } - - [Benchmark(Description = "ClosedXml Create Xlsx")] - public void ClosedXmlCreateTest() - { - var values = GetValues(); - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); - using (var wb = new XLWorkbook()) - { - var ws = wb.Worksheets.Add("Inserting Data"); - ws.Cell(1, 1).InsertData(values); - wb.SaveAs(path); - } - - File.Delete(path); - } - - - [Benchmark(Description = "Epplus Create Xlsx")] - public void EpplusCreateTest() - { -#if DEBUG - ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial; -#endif - var values = GetValues(); - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); - using (var excelFile = new ExcelPackage(new FileInfo(path))) - { - var worksheet = excelFile.Workbook.Worksheets.Add("Sheet1"); - worksheet.Cells["A1"].LoadFromCollection(Collection: values, PrintHeaders: true); - excelFile.Save(); - } - File.Delete(path); - } - - [Benchmark(Description = "OpenXmlSdk Create Xlsx")] - public void OpenXmlSdkCreateTest() - { - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); - // Create a spreadsheet document by supplying the filepath. - // By default, AutoSave = true, Editable = true, and Type = xlsx. - - using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(path, SpreadsheetDocumentType.Workbook)) - { - // Add a WorkbookPart to the document. - WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart(); - workbookpart.Workbook = new Workbook(); - - // Add a WorksheetPart to the WorkbookPart. - WorksheetPart worksheetPart = workbookpart.AddNewPart(); - worksheetPart.Worksheet = new Worksheet(new SheetData()); - - // Add Sheets to the Workbook. - Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook. - AppendChild(new Sheets()); - - // Append a new worksheet and associate it with the workbook. - Sheet sheet = new Sheet() - { - Id = spreadsheetDocument.WorkbookPart. - GetIdOfPart(worksheetPart), - SheetId = 1, - Name = "Sheet1" - }; - sheets.Append(sheet); - - var sheetData = worksheetPart.Worksheet.GetFirstChild(); - foreach (var item in GetValues()) - { - var row = new Row(); - row.Append(new Cell() { CellValue = new CellValue(item.Text1), DataType = CellValues.String }); - row.Append(new Cell() { CellValue = new CellValue(item.Text2), DataType = CellValues.String }); - row.Append(new Cell() { CellValue = new CellValue(item.Text3), DataType = CellValues.String }); - row.Append(new Cell() { CellValue = new CellValue(item.Text4), DataType = CellValues.String }); - row.Append(new Cell() { CellValue = new CellValue(item.Text5), DataType = CellValues.String }); - row.Append(new Cell() { CellValue = new CellValue(item.Text6), DataType = CellValues.String }); - row.Append(new Cell() { CellValue = new CellValue(item.Text7), DataType = CellValues.String }); - row.Append(new Cell() { CellValue = new CellValue(item.Text8), DataType = CellValues.String }); - row.Append(new Cell() { CellValue = new CellValue(item.Text9), DataType = CellValues.String }); - row.Append(new Cell() { CellValue = new CellValue(item.Text10), DataType = CellValues.String }); - sheetData.AppendChild(row); - } - - workbookpart.Workbook.Save(); - - } - File.Delete(path); - } - } - - public class Demo - { - public string Text1 { get; set; } = "Hello World"; - public string Text2 { get; set; } = "Hello World"; - public string Text3 { get; set; } = "Hello World"; - public string Text4 { get; set; } = "Hello World"; - public string Text5 { get; set; } = "Hello World"; - public string Text6 { get; set; } = "Hello World"; - public string Text7 { get; set; } = "Hello World"; - public string Text8 { get; set; } = "Hello World"; - public string Text9 { get; set; } = "Hello World"; - public string Text10 { get; set; } = "Hello World"; - } } diff --git a/benchmarks/MiniExcel.Benchmarks/Properties/PublishProfiles/FolderProfile.pubxml b/benchmarks/MiniExcel.Benchmarks/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..ed3755a --- /dev/null +++ b/benchmarks/MiniExcel.Benchmarks/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,12 @@ + + + + + Release + Any CPU + bin\Release\netcoreapp3.1\publish\ + FileSystem + + \ No newline at end of file diff --git a/benchmarks/MiniExcel.Benchmarks/XlsxAsyncBenchmark.cs b/benchmarks/MiniExcel.Benchmarks/XlsxAsyncBenchmark.cs new file mode 100644 index 0000000..9501eca --- /dev/null +++ b/benchmarks/MiniExcel.Benchmarks/XlsxAsyncBenchmark.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; + +namespace MiniExcelLibs.Benchmarks +{ + public class XlsxAsyncBenchmark : BenchmarkBase + { + [Benchmark(Description = "MiniExcel Async Create Xlsx")] + public async Task MiniExcelCreateAsyncTest() + { + var value = Getvalue(); + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); + using (var stream = File.Create(path)) + await stream.SaveAsAsync(value); + File.Delete(path); + } + + [Benchmark(Description = "MiniExcel Async Template Generate")] + public async Task MiniExcel_Template_Generate_Async_Test() + { + { + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); + const string templatePath = @"TestTemplateBasicIEmumerableFill.xlsx"; + var value = new + { + employees = Enumerable.Range(1, rowCount).Select(s => new { name = "Jack", department = "HR" }) + }; + await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value); + } + } + } +} diff --git a/benchmarks/MiniExcel.Benchmarks/XlsxBenchmark.cs b/benchmarks/MiniExcel.Benchmarks/XlsxBenchmark.cs new file mode 100644 index 0000000..0618bb6 --- /dev/null +++ b/benchmarks/MiniExcel.Benchmarks/XlsxBenchmark.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using ClosedXML.Excel; +using DocumentFormat.OpenXml; +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Spreadsheet; +using ExcelDataReader; +using OfficeOpenXml; + +namespace MiniExcelLibs.Benchmarks +{ + public class XlsxBenchmark : BenchmarkBase + { + [GlobalSetup] + public void SetUp() + { + ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial; + System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); + } + + [Benchmark(Description = "MiniExcel Template Generate")] + public void MiniExcel_Template_Generate_Test() + { + { + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); + const string templatePath = @"TestTemplateBasicIEmumerableFill.xlsx"; + var value = new + { + employees = Enumerable.Range(1, rowCount).Select(s => new { name = "Jack", department = "HR" }) + }; + MiniExcel.SaveAsByTemplate(path, templatePath, value); + } + } + + [Benchmark(Description = "ClosedXml.Report Template Generate")] + public void ClosedXml_Report_Template_Generate_Test() + { + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); + var templatePath = @"TestTemplateBasicIEmumerableFill_ClosedXML_Report.xlsx"; + var template = new ClosedXML.Report.XLTemplate(templatePath); + var value = new + { + employees = Enumerable.Range(1, rowCount).Select(s => new { name = "Jack", department = "HR" }) + }; + template.AddVariable(value); + template.Generate(); + template.SaveAs(path); + } + + [Benchmark(Description = "MiniExcel QueryFirst")] + public void MiniExcel_QueryFirst_Test() + { + MiniExcel.Query(filePath).First(); + } + + [Benchmark(Description = "MiniExcel Query")] + public void MiniExcel_Query() + { + foreach (var item in MiniExcel.Query(filePath)) + { + + } + } + + [Benchmark(Description = "ExcelDataReader QueryFirst")] + public void ExcelDataReader_QueryFirst_Test() + { + using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read)) + using (var reader = ExcelReaderFactory.CreateReader(stream)) + { + var d = new List(); + reader.Read(); + for (int i = 0; i < reader.FieldCount; i++) + d.Add(reader.GetValue(i)); + } + } + + [Benchmark(Description = "ExcelDataReader Query")] + public void ExcelDataReader_Query_Test() + { + using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read)) + using (var reader = ExcelReaderFactory.CreateReader(stream)) + { + while (reader.Read()) + { + var d = new List(); + for (int i = 0; i < reader.FieldCount; i++) + d.Add(reader.GetValue(i)); + } + } + } + + [Benchmark(Description = "Epplus QueryFirst")] + public void Epplus_QueryFirst_Test() + { + using (var p = new ExcelPackage(new FileInfo(filePath))) + { + p.Workbook.Worksheets[0].Row(1); + } + } + + [Benchmark(Description = "Epplus Query")] + public void Epplus_Query_Test() + { + // [c# - How do I iterate through rows in an excel table using epplus? - Stack Overflow](https://stackoverflow.com/questions/21742038/how-do-i-iterate-through-rows-in-an-excel-table-using-epplus) + using (var p = new ExcelPackage(new FileInfo(filePath))) + { + var workSheet = p.Workbook.Worksheets[0]; + var start = workSheet.Dimension.Start; + var end = workSheet.Dimension.End; + for (int row = start.Row; row <= end.Row; row++) + { // Row by row... + for (int col = start.Column; col <= end.Column; col++) + { // ... Cell by cell... + object cellValue = workSheet.Cells[row, col].Text; // This got me the actual value I needed. + } + } + } + } + + [Benchmark(Description = "ClosedXml QueryFirst")] + public void ClosedXml_QueryFirst_Test() + { + using (var workbook = new XLWorkbook(filePath)) + { + workbook.Worksheet(1).Row(1); + } + } + + [Benchmark(Description = "ClosedXml Query")] + public void ClosedXml_Query_Test() + { + using (var workbook = new XLWorkbook(filePath)) + { + workbook.Worksheet(1).Rows(); + } + } + + [Benchmark(Description = "OpenXmlSDK QueryFirst")] + public void OpenXmlSDK_QueryFirst_Test() + { + using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filePath, false)) + { + WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart; + WorksheetPart worksheetPart = workbookPart.WorksheetParts.First(); + SheetData sheetData = worksheetPart.Worksheet.Elements().First(); + var firstRow = sheetData.Elements().First(); + } + } + + [Benchmark(Description = "OpenXmlSDK Query")] + public void OpenXmlSDK_Query_Test() + { + using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filePath, false)) + { + WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart; + WorksheetPart worksheetPart = workbookPart.WorksheetParts.First(); + SheetData sheetData = worksheetPart.Worksheet.Elements().First(); + var firstRow = sheetData.Elements().ToList(); + } + } + + [Benchmark(Description = "MiniExcel Create Xlsx")] + public void MiniExcelCreateTest() + { + var value = Getvalue(); + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); + MiniExcel.SaveAs(path, value); + File.Delete(path); + } + + [Benchmark(Description = "ClosedXml Create Xlsx")] + public void ClosedXmlCreateTest() + { + var value = Getvalue(); + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); + using (var wb = new XLWorkbook()) + { + var ws = wb.Worksheets.Add("Inserting Data"); + ws.Cell(1, 1).InsertData(value); + wb.SaveAs(path); + } + File.Delete(path); + } + + + [Benchmark(Description = "Epplus Create Xlsx")] + public void EpplusCreateTest() + { + var value = Getvalue(); + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); + using (var excelFile = new ExcelPackage(new FileInfo(path))) + { + var worksheet = excelFile.Workbook.Worksheets.Add("Sheet1"); + worksheet.Cells["A1"].LoadFromCollection(Collection: value, PrintHeaders: true); + excelFile.Save(); + } + File.Delete(path); + } + + [Benchmark(Description = "OpenXmlSdk Create xlsx by DOM mode")] + public void OpenXmlSdkCreateByDomModeTest() + { + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); + // Create a spreadsheet document by supplying the filepath. + // By default, AutoSave = true, Editable = true, and Type = xlsx. + + using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(path, SpreadsheetDocumentType.Workbook)) + { + // Add a WorkbookPart to the document. + WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart(); + workbookpart.Workbook = new Workbook(); + + // Add a WorksheetPart to the WorkbookPart. + WorksheetPart worksheetPart = workbookpart.AddNewPart(); + worksheetPart.Worksheet = new Worksheet(new SheetData()); + + // Add Sheets to the Workbook. + Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook. + AppendChild(new Sheets()); + + // Append a new worksheet and associate it with the workbook. + Sheet sheet = new Sheet() + { + Id = spreadsheetDocument.WorkbookPart. + GetIdOfPart(worksheetPart), + SheetId = 1, + Name = "Sheet1" + }; + sheets.Append(sheet); + + var sheetData = worksheetPart.Worksheet.GetFirstChild(); + foreach (var item in Getvalue()) + { + var row = new Row(); + row.Append(new Cell() { CellValue = new CellValue(item.Column1), DataType = CellValues.String }); + row.Append(new Cell() { CellValue = new CellValue(item.Column2), DataType = CellValues.String }); + row.Append(new Cell() { CellValue = new CellValue(item.Column3), DataType = CellValues.String }); + row.Append(new Cell() { CellValue = new CellValue(item.Column4), DataType = CellValues.String }); + row.Append(new Cell() { CellValue = new CellValue(item.Column5), DataType = CellValues.String }); + row.Append(new Cell() { CellValue = new CellValue(item.Column6), DataType = CellValues.String }); + row.Append(new Cell() { CellValue = new CellValue(item.Column7), DataType = CellValues.String }); + row.Append(new Cell() { CellValue = new CellValue(item.Column8), DataType = CellValues.String }); + row.Append(new Cell() { CellValue = new CellValue(item.Column9), DataType = CellValues.String }); + row.Append(new Cell() { CellValue = new CellValue(item.Column10), DataType = CellValues.String }); + sheetData.AppendChild(row); + } + + workbookpart.Workbook.Save(); + + } + File.Delete(path); + } + } +}