Skip to content

Commit

Permalink
add perf tests
Browse files Browse the repository at this point in the history
  • Loading branch information
KovtunV committed Aug 18, 2024
1 parent 46a936c commit 22a01d1
Show file tree
Hide file tree
Showing 163 changed files with 525 additions and 303 deletions.
12 changes: 11 additions & 1 deletion .github/workflows/project-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ jobs:
- name: Build
run: dotnet build -c Release --no-restore

- name: Test
- name: Unit tests
run: dotnet test -c Release --no-restore --no-build -v=normal --collect:"XPlat Code Coverage"

- name: Performance tests
run: dotnet test -c Release --no-restore --no-build -v=normal --filter TestCategory="PerfTests"

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4.0.1
with:
Expand All @@ -39,3 +42,10 @@ jobs:
path: bin/NoStringEvaluating.Extensions.Microsoft.DependencyInjection/Release/*.nupkg
retention-days: 1

- name: Upload performance tests artifacts
uses: actions/upload-artifact@v4
with:
name: performance-tests
path: bin/NoStringEvaluating.Tests/Release/PerformanceTestsResults/PerformanceTests.txt
retention-days: 90

1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PackageVersion Include="Microsoft.Extensions.ObjectPool" Version="8.0.8" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageVersion Include="NoStringEvaluating" Version="2.5.3" />
<PackageVersion Include="Spectre.Console" Version="0.49.1" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageVersion Include="NUnit" Version="4.1.0" />
Expand Down
Binary file modified benchResults/Benchmark.xlsx
Binary file not shown.
2 changes: 1 addition & 1 deletion src/ConsoleApp/Benchmark/Base/BenchBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ private Expression CreateMxParser(string formula)
public const string Formula4 = "(2 + 6 - (13 * 24 + 5 / (123 - 364 + 23))) - (2 + 6 - (13 * 24 + 5 / (123 - 364 + 23))) + (2 + 6 - (13 * 24 + 5 / (123 - 364 + 23))) * 345 * ((897 - 323)/ 23)";

public const string Formula5 = $"{Arg1} * {Arg2} + {Arg3} - {Arg4}";
public const string Formula6 = $"{Arg1} * ({Arg2} + {Arg3}) - {Arg4} / ({Arg5} - {Arg6}) + 45 * {Arg7} + (({Arg8} * 56 + (12 + {Arg9}))) - {Arg10}";
public const string Formula6 = $"{Arg1} * ({Arg2} + {Arg3}) - {Arg4} / ({Arg5} - {Arg6} + 1) + 45 * {Arg7} + (({Arg8} * 56 + (12 + {Arg9}))) - {Arg10}";

public const string Formula7 = $"add(1; 2; 3)";
public const string Formula8 = $"add(add(5; 1) - add(5; 2; 3))";
Expand Down
29 changes: 0 additions & 29 deletions src/NoStringEvaluating.Tests/Helpers/FormulaModelFactory.cs

This file was deleted.

4 changes: 4 additions & 0 deletions src/NoStringEvaluating.Tests/NoStringEvaluating.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@
<ProjectReference Include="..\NoStringEvaluating\NoStringEvaluating.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Spectre.Console" />
</ItemGroup>

</Project>
115 changes: 115 additions & 0 deletions src/NoStringEvaluating.Tests/PerfTests/PerformanceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using System.Diagnostics;
using NoStringEvaluating.Factories;
using NoStringEvaluating.Functions.Base;
using NoStringEvaluating.Functions.Logic;
using NoStringEvaluating.Functions.Math;
using NoStringEvaluating.Models.Values;
using NoStringEvaluating.Tests.PerfTests.Report;
using NUnit.Framework;

namespace NoStringEvaluating.Tests.PerfTests;

[NonParallelizable]
[Category("PerfTests")]
[Explicit("These tests are only run when explicitly specified")]
internal class PerformanceTests
{
private NoStringEvaluator.Facade _serviceFacade;
private ReportContainer _report;

[OneTimeSetUp]
public void GlobalSetup()
{
_report = new();
}

[OneTimeTearDown]
public void GlobalTeardown()
{
ReportWriter.Write(_report);
}

[SetUp]
public void Setup()
{
var functions = new IFunction[]
{
new AddFunction(),
new IfFunction(),
new OrFunction(),
new Func_kov(),
new Func_kovt(),
};

_serviceFacade = NoStringEvaluator.CreateFacade(cfg => cfg.WithoutDefaultFunctions().WithFunctions(functions));
}

[TestCaseSource(nameof(RunSource))]
public void RunFormula(string formulaName, string formula, IDictionary<string, EvaluatorValue> args, long targetElapsedMilliseconds)
{
// arrange
var n = 1_000_000;

var nodes = _serviceFacade.FormulaCache.GetFormulaNodes(formula);

// act, assert
var res = _serviceFacade.Evaluator.CalcNumber(nodes, args);

var ela = Stopwatch.StartNew();
for (var i = 0; i < n; i++)
{
_ = _serviceFacade.Evaluator.Calc(nodes, args);
}

ela.Stop();

_report.Append(formulaName, res, ela.ElapsedMilliseconds, targetElapsedMilliseconds);
}

private static IEnumerable<object[]> RunSource()
{
var args = Enumerable.Range(1, 10).ToDictionary(i => $"Arg{i}", _ => (EvaluatorValue)1.7);

yield return new object[] { "Formula 1", "3 * 9", args, 250 };
yield return new object[] { "Formula 2", "3 * 9 / 456 * 32 + 12 / 17 - 3", args, 170 };
yield return new object[] { "Formula 3", "3 * (9 / 456 * (32 + 12)) / 17 - 3", args, 170 };
yield return new object[] { "Formula 4", "(2 + 6 - (13 * 24 + 5 / (123 - 364 + 23))) - (2 + 6 - (13 * 24 + 5 / (123 - 364 + 23))) + (2 + 6 - (13 * 24 + 5 / (123 - 364 + 23))) * 345 * ((897 - 323)/ 23)", args, 450 };
yield return new object[] { "Formula 5", "Arg1 * Arg2 + Arg3 - Arg4", args, 350 };
yield return new object[] { "Formula 6", "Arg1 * (Arg2 + Arg3) - Arg4 / (Arg5 - Arg6 + 1) + 45 * Arg7 + ((Arg8 * 56 + (12 + Arg9))) - Arg10", args, 580 };
yield return new object[] { "Formula 7", "add(1; 2; 3)", args, 300 };
yield return new object[] { "Formula 8", "add(add(5; 1) - add(5; 2; 3))", args, 370 };
yield return new object[] { "Formula 9", "if(Arg1 > 0; add(56 + 9 / 12 * 123.596; or(78; 9; 5; 2; 4; 5; 8; 7); 45;5); 9) * 24 + 52 -33", args, 830 };
yield return new object[] { "Formula 10", "kov(1; 2; 3) - kovt(8; 9)", args, 350 };
}

public class Func_kov : IFunction
{
public string Name { get; } = "kov";

public bool CanHandleNullArguments { get; }

public InternalEvaluatorValue Execute(List<InternalEvaluatorValue> args, ValueFactory factory)
{
var res = 1d;

for (int i = 0; i < args.Count; i++)
{
res *= args[i];
}

return res;
}
}

public class Func_kovt : IFunction
{
public string Name { get; } = "kovt";

public bool CanHandleNullArguments { get; }

public InternalEvaluatorValue Execute(List<InternalEvaluatorValue> args, ValueFactory factory)
{
return args[0] - args[1];
}
}
}
11 changes: 11 additions & 0 deletions src/NoStringEvaluating.Tests/PerfTests/Report/ReportContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace NoStringEvaluating.Tests.PerfTests.Report;

internal class ReportContainer
{
public List<ReportItem> Items = [];

public void Append(string formula, double result, long elapsedMilliseconds, long targetElapsedMilliseconds)
{
Items.Add(new ReportItem(formula, result, elapsedMilliseconds, targetElapsedMilliseconds));
}
}
37 changes: 37 additions & 0 deletions src/NoStringEvaluating.Tests/PerfTests/Report/ReportExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Globalization;
using Spectre.Console;

namespace NoStringEvaluating.Tests.PerfTests.Report;

internal static class ReportExtensions
{
public static Table AddRows(this Table table, IEnumerable<ReportItem> items)
{
foreach (var item in items)
{
table.AddRow(item);
}

return table;
}

public static void AddRow(this Table table, ReportItem value)
{
table.AddRow(
value.Formula.ToText(),
value.Result.ToText(),
value.ElapsedMilliseconds.ToString().ToText(),
value.TargetElapsedMilliseconds.ToString().ToText(),
value.Attention ? "!".ToText() : string.Empty.ToText());
}

public static Text ToText(this double value)
{
return value.ToString("0.00", CultureInfo.InvariantCulture).ToText();
}

public static Text ToText(this string value)
{
return new Text(value);
}
}
6 changes: 6 additions & 0 deletions src/NoStringEvaluating.Tests/PerfTests/Report/ReportItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace NoStringEvaluating.Tests.PerfTests.Report;

internal record ReportItem(string Formula, double Result, long ElapsedMilliseconds, long TargetElapsedMilliseconds)
{
public bool Attention => ElapsedMilliseconds > TargetElapsedMilliseconds;
}
42 changes: 42 additions & 0 deletions src/NoStringEvaluating.Tests/PerfTests/Report/ReportWriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using NUnit.Framework;
using Spectre.Console;

namespace NoStringEvaluating.Tests.PerfTests.Report;

internal class ReportWriter
{
private const string DIRECTORY = "PerformanceTestsResults";
private const string FILE_PATH = $"{DIRECTORY}/PerformanceTests.txt";

public static void Write(ReportContainer resultsContainer)
{
if (!Directory.Exists(DIRECTORY))
{
Directory.CreateDirectory(DIRECTORY);
}

using var streamWriter = new StreamWriter(FILE_PATH);

var attentionColor = resultsContainer.Items.Any(x => x.Attention) ? "red1" : "gold1";

var table = new Table()
.SquareBorder()
.AddColumns("[gold1]Formula[/]", "[gold1]Result[/]", "[gold1]Elapsed time, ms[/]", "[gold1]Target elapsed time, ms[/]")
.AddColumn(new TableColumn($"[{attentionColor}]Attention[/]").Centered())
.AddRows(resultsContainer.Items);

// Capture the console output
var output = new StringWriter();
Console.SetOut(output);

var console = AnsiConsole.Create(new AnsiConsoleSettings
{
Out = new AnsiConsoleOutput(TestContext.Progress),
ColorSystem = ColorSystemSupport.TrueColor,
});

console.Write(table);

streamWriter.WriteLine(output.ToString());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using NoStringEvaluating.Tests.Models;
using static NoStringEvaluating.Tests.Helpers.FormulaModelFactory;
using NoStringEvaluating.Tests.UnitTests.Models;
using static NoStringEvaluating.Tests.UnitTests.Helpers.FormulaModelFactory;

namespace NoStringEvaluating.Tests.Data;
namespace NoStringEvaluating.Tests.UnitTests.Data;

internal static class CheckFormula
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using NoStringEvaluating.Tests.Models;
using static NoStringEvaluating.Tests.Helpers.FormulaModelFactory;
using NoStringEvaluating.Tests.UnitTests.Models;
using static NoStringEvaluating.Tests.UnitTests.Helpers.FormulaModelFactory;

namespace NoStringEvaluating.Tests.Data;
namespace NoStringEvaluating.Tests.UnitTests.Data;

internal static class EvaluateBoolean
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Globalization;
using NoStringEvaluating.Tests.Models;
using static NoStringEvaluating.Tests.Helpers.FormulaModelFactory;
using NoStringEvaluating.Tests.UnitTests.Models;
using static NoStringEvaluating.Tests.UnitTests.Helpers.FormulaModelFactory;

namespace NoStringEvaluating.Tests.Data;
namespace NoStringEvaluating.Tests.UnitTests.Data;

internal static class EvaluateDateTime
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Globalization;
using NoStringEvaluating.Tests.Models;
using static NoStringEvaluating.Tests.Helpers.FormulaModelFactory;
using NoStringEvaluating.Tests.UnitTests.Models;
using static NoStringEvaluating.Tests.UnitTests.Helpers.FormulaModelFactory;

namespace NoStringEvaluating.Tests.Data;
namespace NoStringEvaluating.Tests.UnitTests.Data;

internal static class EvaluateNumber
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using NoStringEvaluating.Tests.Models;
using static NoStringEvaluating.Tests.Helpers.FormulaModelFactory;
using NoStringEvaluating.Tests.UnitTests.Models;
using static NoStringEvaluating.Tests.UnitTests.Helpers.FormulaModelFactory;

namespace NoStringEvaluating.Tests.Data;
namespace NoStringEvaluating.Tests.UnitTests.Data;

internal static class EvaluateNumberList
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Globalization;
using NoStringEvaluating.Tests.Models;
using static NoStringEvaluating.Tests.Helpers.FormulaModelFactory;
using NoStringEvaluating.Tests.UnitTests.Models;
using static NoStringEvaluating.Tests.UnitTests.Helpers.FormulaModelFactory;

namespace NoStringEvaluating.Tests.Data;
namespace NoStringEvaluating.Tests.UnitTests.Data;

internal static class EvaluateWord
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using NoStringEvaluating.Tests.Models;
using static NoStringEvaluating.Tests.Helpers.FormulaModelFactory;
using NoStringEvaluating.Tests.UnitTests.Models;
using static NoStringEvaluating.Tests.UnitTests.Helpers.FormulaModelFactory;

namespace NoStringEvaluating.Tests.Data;
namespace NoStringEvaluating.Tests.UnitTests.Data;

internal static class EvaluateWordList
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using NoStringEvaluating.Tests.Models;
using static NoStringEvaluating.Tests.Helpers.FormulaModelFactory;
using NoStringEvaluating.Tests.UnitTests.Models;
using static NoStringEvaluating.Tests.UnitTests.Helpers.FormulaModelFactory;

namespace NoStringEvaluating.Tests.Data;
namespace NoStringEvaluating.Tests.UnitTests.Data;

internal static class ParseFormula
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using NoStringEvaluating.Models.Values;
using NUnit.Framework;

namespace NoStringEvaluating.Tests.Functions.Excel;
namespace NoStringEvaluating.Tests.UnitTests.Functions.Excel;

internal class CountFunctionTests : FunctionTests<CountFunction>
{
Expand Down
Loading

0 comments on commit 22a01d1

Please sign in to comment.