Skip to content

Commit

Permalink
Merge pull request #1 from iron-software/use-benchmarkdotnet
Browse files Browse the repository at this point in the history
Use BenchmarkDotNet
  • Loading branch information
artem-iron authored Dec 30, 2022
2 parents d33bdb1 + 0d40d90 commit fce5f31
Show file tree
Hide file tree
Showing 67 changed files with 2,178 additions and 1,617 deletions.
47 changes: 32 additions & 15 deletions IronBenchmarks.App/IronBenchmarks.App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,43 @@
<Nullable>enable</Nullable>
<UserSecretsId>2b9a2db2-1dbc-4ecd-a706-4ee608efc81e</UserSecretsId>
<Company>Iron Software</Company>
<AssemblyVersion>0.0.1</AssemblyVersion>
<FileVersion>0.0.1</FileVersion>
<AssemblyVersion>0.0.2</AssemblyVersion>
<FileVersion>0.0.2</FileVersion>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/iron-software/IronBenchmarks</RepositoryUrl>
<Description>Benchmarking tool that generates reports using IronXL library.</Description>
<Title>IronBenchmarks</Title>
<Version>0.0.2</Version>
<Authors>https://ironsoftware.com/</Authors>
<Product>IronBenchmarks - Tool for benchmark reporting.</Product>
<Copyright>(C) 2022-2023 IronSoftware.com</Copyright>
<PackageReleaseNotes>* Changes benchmark runner to a BenchmarkDotNet
* Reports now include Memory Allocation data
* Reports now draw charts individually for each benchmark
* Adds ability to append new data to previously generted report, allowing to easily benchmark the same library under different versions. Just change the version and run the application with "-a" or "-append" argument
* Adds ability to chose wich sets of benchmarks to run using command-line arguments: "-xl" for Excel, "-pdf" for PDF, "-bc" for BarCode
* Changes the way benchmarks and playlists are structured.
* Adds BenchmarkData, BenchmrakDataEntry and BenchmarkDataPoint classes as a data structure for ReportGenerator.
* Removes IronBenchmarks.Core, IronBenchmarks.IronXL, IronBenchmarks.IronPdf, IronBenchmarks.IronBarCode projects
* Adds unit-tests for IronBenchmarks.Reporting
* Adds two new benchmarks to Excel playlist: Accessing Range Properties and Sort Range</PackageReleaseNotes>
</PropertyGroup>

<ItemGroup>
<None Include="..\README.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.3" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="5.0.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
</ItemGroup>

<ItemGroup>
Expand All @@ -33,18 +56,12 @@
<None Update="appsettings.Production.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="LoadingTestFiles\LoadingTest.xlsx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SortRangeFiles\SortRange.xlsx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\IronBenchmarks.IronBarCode\IronBenchmarks.IronBarCode.csproj" />
<ProjectReference Include="..\IronBenchmarks.IronPdf\IronBenchmarks.IronPdf.csproj" />
<ProjectReference Include="..\IronBenchmarks.IronXL\IronBenchmarks.IronXL.csproj" />
<ProjectReference Include="..\IronBenchmarks.BarCodeLibs\IronBenchmarks.BarCodeLibs.csproj" />
<ProjectReference Include="..\IronBenchmarks.ExcelLibs\IronBenchmarks.ExcelLibs.csproj" />
<ProjectReference Include="..\IronBenchmarks.PdfLibs\IronBenchmarks.PdfLibs.csproj" />
<ProjectReference Include="..\IronBenchmarks.ReportsEngine\IronBenchmarks.Reporting.csproj" />
</ItemGroup>

Expand Down
213 changes: 176 additions & 37 deletions IronBenchmarks.App/Program.cs
Original file line number Diff line number Diff line change
@@ -1,50 +1,189 @@
using IronBenchmarks.IronBarCode;
using IronBenchmarks.IronPdf;
using IronBenchmarks.IronXL;
using IronBenchmarks.Reporting;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Validators;
using IronBenchmarks.App.Configuration;
using IronBenchmarks.BarCodeLibs.Benchmarks;
using IronBenchmarks.ExcelLibs.Benchmarks;
using IronBenchmarks.PdfLibs.Benchmarks;
using IronBenchmarks.Reporting;
using IronBenchmarks.Reporting.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using System.Globalization;
using System.Reflection;
using IronBenchmarks.Reporting.Configuration;

Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
var host = SetupApplication();

var environment = Environment.GetEnvironmentVariable("NETCORE_ENVIRONMENT");
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true)
.AddJsonFile($"appsettings.{environment}.json", true, true)
.AddUserSecrets(Assembly.GetExecutingAssembly(), true)
.AddEnvironmentVariables();
ApplyIronXLLicenseKey(host);

var configurationRoot = builder.Build();
var reportConfig = GetReportConfig(args, host);
var reportGenerator = new ReportGenerator(reportConfig);

var host = Host.CreateDefaultBuilder()
.ConfigureServices((context, services) =>
RunExcelBenchmarks(args, reportConfig, reportGenerator);
RunPdfBenchmarks(args, reportConfig, reportGenerator);
RunBarCodeBenchmarks(args, reportConfig, reportGenerator);

Console.ReadKey();

//#############################################################################

static void RunBarCodeBenchmarks(
string[] args,
IReportingConfig reportConfig,
ReportGenerator reportGenerator)
{
if (args.Contains("-bc"))
{
services.AddSingleton<IAppConfig, AppConfig>(
_ => configurationRoot.GetSection(nameof(AppConfig)).Get<AppConfig>());
services.AddSingleton<IReportingConfig, ReportingConfig>(
_ => configurationRoot.GetSection(nameof(ReportingConfig)).Get<ReportingConfig>());
})
.UseSerilog()
.Build();

var appConfig = ActivatorUtilities.GetServiceOrCreateInstance<IAppConfig>(host.Services);
IronXL.License.LicenseKey = appConfig.LicenseKeyIronXl;
IronBarCode.License.LicenseKey = appConfig.LicenseKeyIronBarCode;
IronPdf.License.LicenseKey = appConfig.LicenseKeyIronPdf;

var reportConfig = ActivatorUtilities.GetServiceOrCreateInstance<IReportingConfig>(host.Services);
var reportGenerator = new ReportGenerator(reportConfig);
reportConfig.ReportsFolder += "\\BarCode";

var barcodeSummaries = new List<Summary>
{
BenchmarkRunner.Run<CreateBarcodeBenchmark>()
};

reportGenerator.GenerateReport(barcodeSummaries, "BarCodeLibs");
}
}

static void RunPdfBenchmarks(
string[] args,
IReportingConfig reportConfig,
ReportGenerator reportGenerator)
{
if (args.Contains("-pdf"))
{
reportConfig.ReportsFolder += "\\PDF";

var config = new ManualConfig()
.WithOptions(ConfigOptions.DisableOptimizationsValidator)
.AddValidator(JitOptimizationsValidator.DontFailOnError)
.AddLogger(ConsoleLogger.Default)
.AddColumnProvider(DefaultColumnProviders.Instance);

var pdfSummaries = new List<Summary>
{
BenchmarkRunner.Run<RenderHtmlToPdfBenchmark>(config),
BenchmarkRunner.Run<LoadingLargeFileBenchmark>(config),
BenchmarkRunner.Run<SavingLargeFileBenchmark>(config),
};

reportGenerator.GenerateReport(pdfSummaries, "PDFLibs");
}
}

static void RunExcelBenchmarks(
string[] args,
IReportingConfig reportConfig,
ReportGenerator reportGenerator)
{
if (args.Contains("-xl"))
{
reportConfig.ReportsFolder += "\\Excel";

var libsWithVersions = GetLibNamesWithVersions(typeof(RandomCellsBenchmark));

var excelSummaries = new List<Summary>
{
BenchmarkRunner.Run<RandomCellsBenchmark>(),
BenchmarkRunner.Run<DateCellBenchmark>(),
BenchmarkRunner.Run<StyleChangeBenchmark>(),
BenchmarkRunner.Run<FormulaCellBenchmark>(),
BenchmarkRunner.Run<LoadLargeFileBenchmark>(),
BenchmarkRunner.Run<SaveLargeFileBenchmark>(),
BenchmarkRunner.Run<SortRangeBenchmark>(),
BenchmarkRunner.Run<AccessingRangePropertiesBenchmark>(),
};

reportGenerator.GenerateReport(excelSummaries, "ExcelLibs", libsWithVersions);
}
}

static Dictionary<string, string> GetLibNamesWithVersions(Type type)
{
var libNames = new Dictionary<string, string>();
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Where(m => m.IsDefined(typeof(BenchmarkAttribute), false));
var fields = type.BaseType?.GetFields() ?? Array.Empty<FieldInfo>();

foreach (var property in fields)
{
var propertyType = property.FieldType;

foreach (var method in methods)
{
if (property.Name.ToLower().Contains(method.Name.ToLower()))
{
var methodName = method.Name;
var assembly = propertyType.Assembly;
var assemblyName = assembly.GetName();
var assemblyVersion = assemblyName.Version;

if (libNames.ContainsKey(methodName))
{
libNames[methodName] = assemblyVersion?.ToString() ?? "";
}
else
{
libNames.Add(methodName, assemblyVersion?.ToString() ?? "");
}

break;
}
}
}

return libNames;
}

static void ApplyIronXLLicenseKey(IHost host)
{
var appConfig = ActivatorUtilities
.GetServiceOrCreateInstance<IAppConfig>(host.Services);

IronXL.License.LicenseKey = appConfig.LicenseKeyIronXl;
}

static IReportingConfig GetReportConfig(string[] args, IHost host)
{
var reportConfig = ActivatorUtilities
.GetServiceOrCreateInstance<IReportingConfig>(host.Services);

if (args.Contains("-a") || args.Contains("-append"))
{
reportConfig.AppendToLastReport = true;
}

return reportConfig;
}

static IHost SetupApplication()
{
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

//var timeTableData = new IronPdfPlayList().RunPlayList(appConfig.ResultsFolderName);
//reportGenerator.GenerateReport(timeTableData, "IronPdf");
var environment = Environment.GetEnvironmentVariable("NETCORE_ENVIRONMENT");
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true)
.AddJsonFile($"appsettings.{environment}.json", true, true)
.AddUserSecrets(Assembly.GetExecutingAssembly(), true)
.AddEnvironmentVariables();

var timeTableData = new IronXlPlayList(new Dictionary<string, string>() { { "IronXL", appConfig.LicenseKeyIronXl } }).RunPlayList(appConfig.ResultsFolderName);
reportGenerator.GenerateReport(timeTableData, "IronXL");
var configurationRoot = builder.Build();

//var timeTableData = new IronBarCodePlayList().RunPlayList(appConfig.ResultsFolderName);
//reportGenerator.GenerateReport(timeTableData, "IronBarCode");
var host = Host.CreateDefaultBuilder()
.ConfigureServices((context, services) =>
{
services.AddSingleton<IAppConfig, AppConfig>(
_ => configurationRoot.GetSection(nameof(AppConfig))
.Get<AppConfig>() ?? new AppConfig());
services.AddSingleton<IReportingConfig, ReportingConfig>(
_ => configurationRoot.GetSection(nameof(ReportingConfig))
.Get<ReportingConfig>() ?? new ReportingConfig());
})
.Build();
return host;
}
Binary file removed IronBenchmarks.App/SortRangeFiles/SortRange.xlsx
Binary file not shown.
9 changes: 5 additions & 4 deletions IronBenchmarks.App/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
"ResultsFolderName": "Results"
},
"ReportingConfig": {
"ChartHeight": 24,
"ChartTitle": "Performance tests",
"ChartWidth": 11,
"ChartHeight": 18,
"ChartWidth": 6,
"ChartsInRow": 4,
"ReportsFolder": "Reports",
"TimeTableStartingRow": 27
"DataTableStartingRow": 1,
"AppendToLastReport": false
}
}
39 changes: 39 additions & 0 deletions IronBenchmarks.BarCodeLibs/Benchmarks/BenchmarkBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Microsoft.Extensions.Configuration;
using System.IO;
using System.Reflection;

namespace IronBenchmarks.BarCodeLibs.Benchmarks
{
public abstract class BenchmarkBase
{
public BenchmarkBase()
{
SetupLicenses();
EnsureResultsFolderExists();
}

public static void SetupLicenses()
{
var builder = new ConfigurationBuilder()
.AddUserSecrets(Assembly.GetExecutingAssembly(), true);
var configuration = builder.Build();
var appConfig = configuration.GetSection("AppConfig");
var licenseKeyIronBarCode = appConfig["LicenseKeyIronBarCode"];

IronBarCode.License.LicenseKey = licenseKeyIronBarCode;
}

public static void EnsureResultsFolderExists()
{
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var reportsFolder = Path.Combine(path ?? "", "Results");

if (!Directory.Exists(reportsFolder))
{
Directory.CreateDirectory(reportsFolder);
}
}

public abstract void Iron_BarCode();
}
}
21 changes: 21 additions & 0 deletions IronBenchmarks.BarCodeLibs/Benchmarks/CreateBarcodeBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using BenchmarkDotNet.Attributes;
using System;

namespace IronBenchmarks.BarCodeLibs.Benchmarks
{
[ShortRunJob]
[MemoryDiagnoser]
public class CreateBarcodeBenchmark : BenchmarkBase
{
private readonly string text = Guid.NewGuid().ToString();

[Benchmark]
public override void Iron_BarCode()
{
IronBarCode.QRCodeWriter.CreateQrCode(
text,
500,
IronBarCode.QRCodeWriter.QrErrorCorrectionLevel.Medium);
}
}
}
15 changes: 15 additions & 0 deletions IronBenchmarks.BarCodeLibs/IronBenchmarks.BarCodeLibs.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<UserSecretsId>84554a44-3362-4f16-874e-896b2b5196c1</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.3" />
<PackageReference Include="BarCode" Version="2022.11.10702" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
</ItemGroup>

</Project>
Loading

0 comments on commit fce5f31

Please sign in to comment.