Skip to content

Commit

Permalink
(aviita) Fix performance issue with CaseSensitivity enabled pieterder…
Browse files Browse the repository at this point in the history
  • Loading branch information
mrxrsd committed Aug 21, 2021
1 parent e519934 commit 5dfc09c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 11 deletions.
3 changes: 2 additions & 1 deletion Jace.Benchmark/BenchMarkOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class BenchMarkOperation<T>
{
public string Formula { get; set; }
public BenchmarkMode Mode { get; set; }
public Func<ICalculationEngine<T>, string, TimeSpan> BenchMarkDelegate { get; set; }
public Func<ICalculationEngine<T>, string, Dictionary<string, double>, TimeSpan> BenchMarkDelegate { get; set; }
public Dictionary<string, T> VariableDict { get; set; }
}
}
23 changes: 16 additions & 7 deletions Jace.Benchmark/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ private static DataTable Benchmark(BenchmarkMode mode, CaseSensitivity caseSensi

BenchMarkOperation<double>[] benchmarks = {
new BenchMarkOperation<double>() { Formula = "2+3*7", Mode = BenchmarkMode.Static, BenchMarkDelegate = BenchMarkCalculationEngine },
new BenchMarkOperation<double>() { Formula = "something2 - (var1 + var2 * 3)/(2+3)", Mode = BenchmarkMode.Simple, BenchMarkDelegate = BenchMarkCalculationEngine,
VariableDict = new Dictionary<string, double>(){{"var1", 4.5642}, {"var2", 845.4235}, { "something2", 25038.66 } } },
new BenchMarkOperation<double>() { Formula = "logn(var1, (2+3) * 500)", Mode = BenchmarkMode.SimpleFunction , BenchMarkDelegate = BenchMarkCalculationEngineFunctionBuild },
new BenchMarkOperation<double>() { Formula = "(var1 + var2 * 3)/(2+3) - something", Mode = BenchmarkMode.Simple , BenchMarkDelegate = BenchMarkCalculationEngineFunctionBuild },
};
Expand All @@ -89,25 +91,25 @@ private static DataTable Benchmark(BenchmarkMode mode, CaseSensitivity caseSensi
{
if (caseSensitivity == CaseSensitivity.All || caseSensitivity == CaseSensitivity.CaseInSensitive)
{
duration = benchmark.BenchMarkDelegate(interpretedEngine, benchmark.Formula);
duration = benchmark.BenchMarkDelegate(interpretedEngine, benchmark.Formula, benchmark.VariableDict);
table.AddBenchmarkRecord("Interpreted", false, benchmark.Formula, null, NumberOfTests, duration);
}

if (caseSensitivity == CaseSensitivity.All || caseSensitivity == CaseSensitivity.CaseSensitive)
{
duration = benchmark.BenchMarkDelegate(interpretedEngineCaseSensitive, benchmark.Formula);
duration = benchmark.BenchMarkDelegate(interpretedEngineCaseSensitive, benchmark.Formula, benchmark.VariableDict);
table.AddBenchmarkRecord("Interpreted", true, benchmark.Formula, null, NumberOfTests, duration);
}

if (caseSensitivity == CaseSensitivity.All || caseSensitivity == CaseSensitivity.CaseInSensitive)
{
duration = benchmark.BenchMarkDelegate(compiledEngine, benchmark.Formula);
duration = benchmark.BenchMarkDelegate(compiledEngine, benchmark.Formula, benchmark.VariableDict);
table.AddBenchmarkRecord("Compiled", false, benchmark.Formula, null, NumberOfTests, duration);
}

if (caseSensitivity == CaseSensitivity.All || caseSensitivity == CaseSensitivity.CaseSensitive)
{
duration = benchmark.BenchMarkDelegate(compiledEngineCaseSensitive, benchmark.Formula);
duration = benchmark.BenchMarkDelegate(compiledEngineCaseSensitive, benchmark.Formula, benchmark.VariableDict);
table.AddBenchmarkRecord("Compiled", true, benchmark.Formula, null, NumberOfTests, duration);
}
}
Expand Down Expand Up @@ -153,21 +155,28 @@ private static DataTable Benchmark(BenchmarkMode mode, CaseSensitivity caseSensi
return table;
}

private static TimeSpan BenchMarkCalculationEngine(ICalculationEngine<double> engine, string functionText)
private static TimeSpan BenchMarkCalculationEngine(ICalculationEngine<double> engine, string functionText, Dictionary<string, double> variableDict)
{
DateTime start = DateTime.Now;

for (int i = 0; i < NumberOfTests; i++)
{
engine.Calculate(functionText);
if (variableDict == null)
{
engine.Calculate(functionText);
}
else
{
engine.Calculate(functionText, new Dictionary<string, double>(variableDict));
}
}

DateTime end = DateTime.Now;

return end - start;
}

private static TimeSpan BenchMarkCalculationEngineFunctionBuild(ICalculationEngine<double> engine, string functionText)
private static TimeSpan BenchMarkCalculationEngineFunctionBuild(ICalculationEngine<double> engine, string functionText, Dictionary<string, double> variableDict)
{
DateTime start = DateTime.Now;

Expand Down
16 changes: 16 additions & 0 deletions Jace.Tests/DecimalCalculationEngineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,22 @@ public void TestCalculateFormulaWithCaseSensitiveVariables1Compiled()
Assert.AreEqual(8.5m, result);
}

[TestMethod]
public void TestCalculateFormulaWithCaseSensitiveThrows()
{
Dictionary<string, decimal> variables = new Dictionary<string, decimal>();
variables.Add("var1", 1);
variables.Add("var2", 1);

var engine = CalculationEngine.New<decimal>(new JaceOptions
{
CaseSensitive = true
});

var ex = AssertExtensions.ThrowsException<VariableNotDefinedException>(() => engine.Calculate("VaR1*vAr2", variables));
Assert.AreEqual("The variable \"VaR1\" used is not defined.", ex.Message);
}

[TestMethod]
public void TestCalculateFormulaWithCaseSensitiveVariables1Interpreted()
{
Expand Down
16 changes: 16 additions & 0 deletions Jace.Tests/DoubleCalculationEngineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,22 @@ public void TestCalculateFormulaWithCaseSensitiveVariables1Compiled()
Assert.AreEqual(8.5, result);
}

[TestMethod]
public void TestCalculateFormulaWithCaseSensitiveThrows()
{
Dictionary<string, double> variables = new Dictionary<string, double>();
variables.Add("var1", 1);
variables.Add("var2", 1);

var engine = CalculationEngine.New<double>(new JaceOptions
{
CaseSensitive = true
});

var ex = AssertExtensions.ThrowsException<VariableNotDefinedException>(() => engine.Calculate("VaR1*vAr2", variables));
Assert.AreEqual("The variable \"VaR1\" used is not defined.", ex.Message);
}

[TestMethod]
public void TestCalculateFormulaWithCaseSensitiveVariables1Interpreted()
{
Expand Down
7 changes: 4 additions & 3 deletions Jace/GenericCalculationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ public abstract class GenericCalculationEngine<T> : IInternalCalculationEngine<T
/// <param name="options">The <see cref="JaceOptions"/> to configure the behaviour of the engine.</param>
internal GenericCalculationEngine(JaceOptions options)
{
this.caseSensitive = options.CaseSensitive;
this.executionFormulaCache = new MemoryCache<string, Func<IDictionary<string, T>, T>>(options.CacheMaximumSize, options.CacheReductionSize);
this.FunctionRegistry = new FunctionRegistry<T>(false);
this.ConstantRegistry = new ConstantRegistry<T>(false);
this.FunctionRegistry = new FunctionRegistry<T>(caseSensitive);
this.ConstantRegistry = new ConstantRegistry<T>(caseSensitive);
this.cultureInfo = options.CultureInfo;
this.cacheEnabled = options.CacheEnabled;
this.optimizerEnabled = options.OptimizerEnabled;
this.caseSensitive = options.CaseSensitive;


this.random = new Random();

Expand Down

0 comments on commit 5dfc09c

Please sign in to comment.