Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add benchmarks project #1091

Merged
merged 1 commit into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,5 @@ $RECYCLE.BIN/
examples/packages
examples/.vs/
/artifacts

BenchmarkDotNet.Artifacts
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>

<!-- SourceLink related properties https://github.com/dotnet/SourceLink#using-sourcelink -->
<!-- Optional: Publish the repository URL in the built .nupkg (in the NuSpec <Repository> element) -->
<PublishRepositoryUrl>true</PublishRepositoryUrl>
Expand Down
58 changes: 58 additions & 0 deletions benchmarks/NPOI.Benchmarks/LargeExcelFileBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System.Net;
using BenchmarkDotNet.Attributes;
using NPOI.XSSF.UserModel;

namespace NPOI.Benchmarks;

[ShortRunJob]
[MemoryDiagnoser]
public class LargeExcelFileBenchmark
{
private static XSSFWorkbook _loadedWorkBook;
private static MemoryStream _memoryStream;
private string _filePath;

[GlobalSetup]
public void GlobalSetup()
{
// a 17MB Excel file is large so download it only when needed
_filePath = Path.Combine(Path.GetTempPath(), "test-performance.xlsx");
if (!File.Exists(_filePath))
{
Console.WriteLine("Downloading file...");
new WebClient().DownloadFile(
"https://github.com/GrapeCity/GcExcel-Java/raw/master/benchmark/files/test-performance.xlsx",
_filePath);
Console.WriteLine("File downloaded");
}

var copyPath = Path.Combine(Path.GetTempPath(), "test-performance-copy.xlsx");
if (!File.Exists(copyPath))
{
File.Copy(_filePath, copyPath);
}

_loadedWorkBook = new XSSFWorkbook(copyPath);
_memoryStream = new MemoryStream();
}

[Benchmark]
public void Load()
{
var workbook = new XSSFWorkbook(_filePath);
workbook.Dispose();
}

[Benchmark]
public void Write()
{
_memoryStream.Seek(0, SeekOrigin.Begin);
_loadedWorkBook.Write(_memoryStream, leaveOpen: true);
}

[Benchmark]
public void Evaluate()
{
_loadedWorkBook.GetCreationHelper().CreateFormulaEvaluator().EvaluateAll();
}
}
17 changes: 17 additions & 0 deletions benchmarks/NPOI.Benchmarks/NPOI.Benchmarks.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\ooxml\NPOI.OOXML.Core.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.5" />
</ItemGroup>

</Project>
4 changes: 4 additions & 0 deletions benchmarks/NPOI.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
using BenchmarkDotNet.Running;
using NPOI.Benchmarks;

BenchmarkSwitcher.FromAssembly(typeof(LargeExcelFileBenchmark).Assembly).Run();
140 changes: 140 additions & 0 deletions benchmarks/NPOI.Benchmarks/RangeValuesBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
using BenchmarkDotNet.Attributes;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;

namespace NPOI.Benchmarks;

[MemoryDiagnoser]
public class RangeValuesBenchmark
{
private static readonly MemoryStream _memoryStream = new();

[Params(1_000)]
public int RowCount { get; set; }

[Params(30)]
public int ColumnCount { get; set; }

[Benchmark]
public void Double()
{
var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("poi");

for (var r = 0; r < RowCount; r++)
{
var row = worksheet.CreateRow(r);
for (var c = 0; c < ColumnCount; c++)
{
row.CreateCell(c).SetCellValue(r + c);
}
}

for (var r = 0; r < RowCount; r++)
{
var row = worksheet.GetRow(r);
for (var c = 0; c < ColumnCount; c++)
{
var d = row.GetCell(c).NumericCellValue;
}
}

WriteFileAndClose(workbook);
}

[Benchmark]
public void String()
{
var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("poi");

var random = new Random();
const string alphaNumericString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

for (var r = 0; r < RowCount; r++)
{
var row = worksheet.CreateRow(r);
for (var c = 0; c < ColumnCount; c++)
{
row.CreateCell(c).SetCellValue(alphaNumericString[random.Next(25)].ToString());
}
}

for (var r = 0; r < RowCount; r++)
{
var row = worksheet.GetRow(r);
for (var c = 0; c < ColumnCount; c++)
{
var s = row.GetCell(c).StringCellValue;
}
}

WriteFileAndClose(workbook);
}

[Benchmark]
public void Date()
{
var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("poi");

for (var r = 0; r < RowCount; r++)
{
var row = worksheet.CreateRow(r);
for (var c = 0; c < ColumnCount; c++)
{
row.CreateCell(c).SetCellValue(DateTime.Now);
}
}

for (var r = 0; r < RowCount; r++)
{
var row = worksheet.GetRow(r);
for (var c = 0; c < ColumnCount; c++)
{
var d = row.GetCell(c).DateCellValue;
}
}

WriteFileAndClose(workbook);
}

[Benchmark]
public void Formulas()
{
var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("poi");

for (var r = 0; r < RowCount; r++)
{
var row = worksheet.CreateRow(r);
for (var c = 0; c < 2; c++)
{
row.CreateCell(c).SetCellValue(r + c);
}
}

for (var r = 0; r < RowCount; r++)
{
var row = worksheet.GetRow(r);
for (var c = 2; c < ColumnCount + 2; c++)
{
var cell = row.CreateCell(c);
var reference1 = new CellReference(r, c - 2);
var reference2 = new CellReference(r, c - 1);
cell.CellFormula = $"SUM({reference1.FormatAsString()}, {reference2.FormatAsString()})";
}
}

workbook.GetCreationHelper().CreateFormulaEvaluator().EvaluateAll();

WriteFileAndClose(workbook);
}

private static void WriteFileAndClose(XSSFWorkbook workbook)
{
_memoryStream.Seek(0, SeekOrigin.Begin);
workbook.Write(_memoryStream, leaveOpen: true);
workbook.Close();
}
}
7 changes: 7 additions & 0 deletions solution/NPOI.Core.Test.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NPOI.OOXML.TestCases.Core",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_build", "..\build\_build.csproj", "{94B18BCF-84E8-401F-BAAB-0496AA136628}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NPOI.Benchmarks", "..\benchmarks\NPOI.Benchmarks\NPOI.Benchmarks.csproj", "{3DA1149D-46F8-4181-9976-E002BF2BFB76}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -60,6 +62,11 @@ Global
{DA2CA3BD-1CAC-470C-9FA2-611A5768A76A}.Release|Any CPU.Build.0 = Release|Any CPU
{94B18BCF-84E8-401F-BAAB-0496AA136628}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{94B18BCF-84E8-401F-BAAB-0496AA136628}.Release|Any CPU.ActiveCfg = Release|Any CPU
{94B18BCF-84E8-401F-BAAB-0496AA136628}.Release|Any CPU.Build.0 = Release|Any CPU
{3DA1149D-46F8-4181-9976-E002BF2BFB76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3DA1149D-46F8-4181-9976-E002BF2BFB76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3DA1149D-46F8-4181-9976-E002BF2BFB76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3DA1149D-46F8-4181-9976-E002BF2BFB76}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down