Farfetch / rules-framework

A generic framework that allows defining and evaluating rules for complex business scenarios.
MIT License
40 stars 7 forks source link

Allow pre-compilation of rules conditions #122

Closed luispfgarces closed 1 year ago

luispfgarces commented 1 year ago

Description

Adds functionality to pre-compile rules' conditions in order to speed up evaluation times. Putting it simply: it adds a middleware component that intercepts rules loaded from the data source or being written to the data source, and compiles them to a lambda expression. The resultant lambda expression is stored on the data source, thanks to the new IConditionNode<TConditionType>.Properties dictionary property, which enables to store the compiled lambda expression. This compiled lambda expression is then loaded from the data source avoiding re-compiling the rules' conditions again. This development also includes a conditions eval engine prepared to evaluate compiled rules.

A new project with a Benchmark.Net implementation was already added to measure some performance numbers. Unfortunately, I was unable to assess the improvement of this implementation vs. the master codebase. I'm including the performance numbers taken from the implementation as-is for your consideration.

Benchmark Method EnableCompilation Mean (ns) Error (ns) StdDev (ns) Skewness Kurtosis BranchInstructions/Op BranchMispredictions/Op Gen0 Allocated (KB)
1 - Test rule (1 rule, 1 condition) RunAsync FALSE 660,5 3,08 2,88 -0,0707 1,751 2122 2 0,1287 1,59
1 - Test rule (1 rule, 1 condition) RunAsync TRUE 584,1 3,69 3,27 -0,0777 2,724 1841 2 0,1402 1,72
2 - Songs (2 rules, various conditions) RunAsync FALSE 2003,9 9,34 8,73 -0,3514 2,111 7089 8 0,3166 3,92
2 - Songs (2 rules, various conditions) RunAsync TRUE 958,8 5,35 5,01 -0,2135 2,135 3619 2 0,1564 1,93
3 - Poker rules (100+ rules, various conditions) RunAsync FALSE 39190 263 246 -0,166 2,221 141307 239 6,2866 77,37
3 - Poker rules (100+ rules, various conditions) RunAsync TRUE 20910 148 139 0,676 2,303 75102 65 2,9297 36,15

Here's how they compare:

Benchmark Time taken [Interpreted] - ns Time taken [Compiled] - ns Time taken [Interpreted vs. Compiled] - % gain Memory [Interpreted] - KB Memory [Compiled] - KB Memory [Interpreted vs. Compiled] - % gain
1 660,50 584,1 11,57% 1,59 1,72 -8,18%
2 2003,9 958,8 52,15% 3,92 1,93 50,77%
3 39190 20910 46,64% 77,37 36,15 53,28%

Related to #49.

Change checklist

Please also check the I want to contribute guidelines and make sure you have done accordingly.

Disclaimer

By sending us your contributions, you are agreeing that your contribution is made subject to the terms of our Contributor Ownership Statement

jdromeiro commented 1 year ago

More of a nit-pick, but in the header of the Pull Request consider changing Classic to Interpreted.