我在 EPPlus 和 Spreadsheet Gear 之间进行了简单的性能测试,看看是否存在任何显着差异,足以证明购买 Spreadsheet Gear 的合理性。
我不是这两个应用程序的专家,因此测试可能不是以最有效的方式编写的。
测试执行以下操作: 1. 打开一个现有的 1000 行 3 列的 Excel 文件。将三个值保存到一个实体中,该实体保存到 List<> 中。 2. 打开一个新的 Excel 对象 3. 创建包含每列标题的标题行(粗体)。 4. 写回 1000 个实体。 5. 保存新的 Excel 文件。
如果我在 EPPlus 获胜后运行此测试(大约时间为 EPPlus = 280ms,SG = 500ms)。如果我连续运行测试 10 次(for 循环打开、复制、保存 10 次),Spreadsheet Gear 会更快(每个文件大约时间:EPPlus = 165ms,SG = 95ms)。对于 20 次测试,大约时间为 EPPlus = 160ms/文件,SG = 60ms/文件。
似乎(至少在某种程度上)我创建的文件越多,Spreadsheet Gears 就越快。 谁能解释为什么 EPPlus 在运行连续测试时速度较慢?我可以更改代码来更改此设置吗?
EPPlus测试功能:
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;
主要功能
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,但我确实编写了一个测试,尝试做与您正在做的相同的事情。使用 SpreadsheetGear 2012 由于我没有您的起始工作簿,因此我首先构建工作簿。然后,我使用了更优化的 SpreadsheetGear API。第一次运行时,我在 SpreadsheetGear 2012 上得到了 141 毫秒的时间。第一次运行后,在运行 Win7 x86 的超频 Core i7-980x 上每次运行都得到了 9 或 10 毫秒的时间,并且在没有调试器的情况下运行了发布版本。
我已将代码粘贴到下面(只需将其粘贴到 .NET 4.0 C# 控制台应用程序中)。
我的另一个想法是,这是一个非常小的测试用例。要真正了解 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);
}
}
}
关于使用 EPPlus 与 Spreadsheet Gear 读取/写入多个文件时的性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13512069/