使用EPPlus与Spreadsheet Gear读取/写入多个文件时的性能差异

我已经在EPPlus和Spreadsheet Gear之间做了一个简单的性能testing,看看是否有任何显着的差异,可以购买Spreadsheet Gear。

我不是任何应用程序的专家,所以有可能testing不是最有效的方式。

testing执行以下操作:1.打开一个具有1000行和3列的现有Excel文件。 将这三个值保存到保存到List <>中的实体中。 2.打开一个新的Excel对象3.用每列的标题创build一个标题行(粗体)。 4.回写1000个实体。 5.保存新的Excelfile。

如果我一旦EPPlus出来赢家(大约是EPPlus = 280ms,SG = 500ms)运行这个testing。 如果我连续10次运行testing(for循环打开,复制,保存10个单独的时间),Spreadsheet Gear的速度更快(大约每个文件的时间:EPPlus = 165ms,SG = 95ms)。 对于20次testing,近似时间是EPPlus = 160ms / file和SG = 60ms / file。

看起来(至less在某种程度上),电子表格齿轮越来越快,我创build的文件越多。 任何人都可以解释为什么运行连续testing时EPPlus是较慢的? 我可以修改代码来改变它吗?

EPPlustestingfunction:

var timer = new Stopwatch(); timer.Start(); var data = new List<Item>(); using (var excelIn = new ExcelPackage(new FileInfo(folder + fileIn))) { var sheet = excelIn.Workbook.Worksheets[1]; var row = 2; while (sheet.Cells[row, 1].Value != null) { data.Add(new Item() { Id = int.Parse(sheet.Cells[row, 1].Text), Title = sheet.Cells[row, 2].Text, Value = int.Parse(sheet.Cells[row, 3].Text) }); row++; } } using (var excelOut = new ExcelPackage()) { var sheet = excelOut.Workbook.Worksheets.Add("Out"); sheet.Cells.LoadFromCollection(data); sheet.InsertRow(1, 1); sheet.Cells[1, 1, 1, 3].Style.Font.Bold = true; sheet.Cells[1, 1].Value = "Id"; sheet.Cells[1, 2].Value = "Title"; sheet.Cells[1, 3].Value = "Value"; excelOut.SaveAs(new FileInfo(folder + "EPPlus_" + Guid.NewGuid() + ".xlsx")); } timer.Stop(); return timer.ElapsedMilliseconds; 

电子表格齿轮:

 var timer = new Stopwatch(); timer.Start(); var data = new List<Item>(); var excelIn = Factory.GetWorkbook(folder + fileIn); var sheetIn = excelIn.Worksheets[0]; var rowIn = 1; while (sheetIn.Cells[rowIn, 0].Value != null) { data.Add(new Item() { Id = int.Parse(sheetIn.Cells[rowIn, 0].Text), Title = sheetIn.Cells[rowIn, 1].Text, Value = int.Parse(sheetIn.Cells[rowIn, 2].Text) }); rowIn++; } excelIn.Close(); var excelOut = Factory.GetWorkbook(); var sheetOut = excelOut.Worksheets.Add(); sheetOut.Name = "Out"; var rowOut = 0; sheetOut.Cells[rowOut, 0, rowOut, 2].Font.Bold = true; sheetOut.Cells[rowOut, 0].Value = "Id"; sheetOut.Cells[rowOut, 1].Value = "Title"; sheetOut.Cells[rowOut++, 2].Value = "Value"; foreach (var item in data) { sheetOut.Cells[rowOut, 0].Value = item.Id; sheetOut.Cells[rowOut, 1].Value = item.Title; sheetOut.Cells[rowOut++, 2].Value = item.Value; } excelOut.SaveAs(folder + "SpreadsheetGear_" + Guid.NewGuid() + ".xlsx", FileFormat.OpenXMLWorkbook); excelOut.Close(); timer.Stop(); return timer.ElapsedMilliseconds; 

主function

 var runs = 1; var testerG = new TestSpreadsheetGear(); var testerE = new TestEpPlus(); var msE = 0.0; var msG = 0.0; var i = 0; for (i = 0; i < runs; ++i) { msG += new TestSpreadsheetGear().Run(folder, originalFile); } for(i = 0; i < runs; ++i) { msE += new TestEpPlus().Run(folder, originalFile); } Console.WriteLine("Spreadsheet time: " + msG + ". Per file: " + msG / runs); Console.WriteLine("EP Plus time: " + msE + ". Per file: " + msE / runs); Console.ReadKey(); 

我相信,你所看到的结果的原因是,在第一次运行的.NET CLR必须JIT的代码。 由于SpreadsheetGear是一个完整的电子表格引擎(相对于读/写库),所以有更多的代码给JIT–因此SpreadsheetGear的第一次运行比EPPlus需要更长的时间(我在这里进行推测,但是有很多经验以过去10年的.NET代码为基准)。

我没有安装EPPlus,但我写了一个testing,试图做同样的事情,你在做什么。 与SpreadsheetGear 2012因为我没有你的起始工作簿,我首先build立工作簿。 然后,我使用了更优化的SpreadsheetGear API。 我第一次运行时,SpreadsheetGear 2012获得了141毫秒的时间。第一次运行后,运行Win7 x86的超频Core i7-980x每次运行9或10毫秒,而没有debugging器的版本运行。

我粘贴了下面的代码(只需粘贴到.NET 4.0 C#控制台应用程序中)。

我还有一个想法是,这是一个非常小的testing案例。 要真正看到SpreadsheetGear 2012的性能,请尝试使用100,000行甚至100万行。

免责声明:我自己的SpreadsheetGear LLC

 using System; using System.Collections.Generic; using System.Diagnostics; using SpreadsheetGear; namespace SGvsEPPlus { class Program { internal struct Item { internal Item(int id, string title, int value) { Id = id; Title = title; Value = value; } internal int Id; internal string Title; internal int Value; } static void Test(int rows) { string filename = @"C:\tmp\MyWorkbook.xlsx"; Console.Write("Test({0})...", rows); var timer = new Stopwatch(); // Create workbook since we don't have poster's original workbook. timer.Restart(); var workbook = Factory.GetWorkbook(); var values = (SpreadsheetGear.Advanced.Cells.IValues)workbook.Worksheets[0]; for (int row = 1; row <= rows; row++) { values.SetNumber(row, 0, row); values.SetText(row, 1, "Title " + row); values.SetNumber(row, 2, row * 10); } Console.Write("Create workbook={0:0}...", timer.Elapsed.TotalMilliseconds); // Save workbook timer.Restart(); workbook.SaveAs(filename, FileFormat.OpenXMLWorkbook); Console.Write("Save workbook={0:0}...", timer.Elapsed.TotalMilliseconds); // Track total time of original test. var totalTimer = Stopwatch.StartNew(); // Open workbook timer.Restart(); var excelIn = Factory.GetWorkbook(filename); Console.Write("Open excelIn={0:0}...", timer.Elapsed.TotalMilliseconds); // Copy workbook to list timer.Restart(); var sheetIn = excelIn.Worksheets[0]; var valuesIn = (SpreadsheetGear.Advanced.Cells.IValues)sheetIn; var rowIn = 1; var data = new List<Item>(rows); while (valuesIn[rowIn, 0] != null) { data.Add(new Item( (int)valuesIn[rowIn, 0].Number, valuesIn[rowIn, 1].Text, (int)valuesIn[rowIn, 2].Number)); rowIn++; } excelIn.Close(); // Not necessary but left for consistency. Console.Write("excelIn->data={0:0}...", timer.Elapsed.TotalMilliseconds); timer.Restart(); var excelOut = Factory.GetWorkbook(); var sheetOut = excelOut.Worksheets[0]; var valuesOut = (SpreadsheetGear.Advanced.Cells.IValues)sheetOut; sheetOut.Name = "Out"; var rowOut = 0; sheetOut.Cells[rowOut, 0, rowOut, 2].Font.Bold = true; sheetOut.Cells[rowOut, 0].Value = "Id"; sheetOut.Cells[rowOut, 1].Value = "Title"; sheetOut.Cells[rowOut++, 2].Value = "Value"; foreach (var item in data) { valuesOut.SetNumber(rowOut, 0, item.Id); valuesOut.SetText(rowOut, 1, item.Title); valuesOut.SetNumber(rowOut, 2, item.Value); rowOut++; } Console.Write("data->excelOut={0:0}...", timer.Elapsed.TotalMilliseconds); timer.Restart(); excelOut.SaveAs(@"C:\tmp\SpreadsheetGear_" + Guid.NewGuid() + ".xlsx", FileFormat.OpenXMLWorkbook); excelOut.Close(); // Again - not necessary. Console.WriteLine("Save excelOut={0:0}...", timer.Elapsed.TotalMilliseconds); Console.WriteLine(" Total={0:0}", totalTimer.Elapsed.TotalMilliseconds); } static void Main(string[] args) { // Do it three times with 1000 rows. Note that the first // time takes longer because code must be JITted. Test(1000); Test(1000); Test(1000); } } }