This pull request adds a series of performance improvements to reduce time-taken and memory consumption where possible. Here's a summary of all changes.
Core
Created the types PropertiesDictionary and DictionarySlim<TKey, TValue>.
The DictionarySlim<TKey, TValue> is a IDictionary<TKey, TValue> lightweight implementation that uses a backing array that is faster to a certain point than the default .Net Dictionary<TKey, TValue>.
The PropertiesDictionary automatically switches from DictionarySlim<TKey, TValue> to Dictionary<TKey, TValue> when the number of properties reaches 6+.
Remove LINQ usage on CompilationRulesSourceMiddleware.
Avoid usage of as operator (which causes a box conversion) and use explicit cast instead.
Add the AggressiveInlining hint to several methods in order to instruct the JIT to incorporate the annotated methods where they are called.
Use ordinal strings comparison where possible.
Remove old pattern-matching logic on DeferredEval.
Refactor MatchOneAsync to eval rules until the first match (and stops) - starts the evaluation at top or bottom according to the PriorityCriteria configured.
In-memory provider
Replace IEnumerable with arrays on data models - ensure exact memory allocation and allow usage of fast algorithms to read/write to the data source.
Refactored internal APIs to use IReadOnlyCollection instead of IEnumerable, which favors the use of faster index-based algorithms.
Avoid usage of LINQ and use custom-made algorithms for converting from data models to the core Rule model, and vice-versa.
Avoid usage of LINQ on InMemoryRulesStorage and use specific optimized List methods. Also, avoid creating List copies.
Refactored RuleFactory to not use the RuleBuilder API and manually build the core Rule model from data models - this bypasses the validations, which at this point, we assume that the data written to the in-memory data source is correct.
MongoDB provider
Created an initializer from MongoDB database, collection, and indexes - ensures initialization only runs once on the app lifecycle.
Forced property ordering on MongoDB data models with [BsonElement(Order = <number>)].
Replace IEnumerable with arrays on data models - ensure exact memory allocation and allow usage of fast algorithms to read/write to the data source.
Avoid usage of LINQ and use custom-made algorithms for converting from data models to the core Rule model, and vice-versa.
Added serialization of rules' content - DynamicToStrongTypeContentSerializer due to the same change on the MongoDB driver highlighted above. Adjusted the deserialization according to changes.
Benchmark tests
Add MongoDB to benchmark evaluation.
Removed test implementation of in-memory data source and started using the real in-memory data source.
Added support to tear down the data source after the benchmark runs.
Other tests
Converted MongoDB tests to run with and without compilation.
Description
This pull request adds a series of performance improvements to reduce time-taken and memory consumption where possible. Here's a summary of all changes.
Core
PropertiesDictionary
andDictionarySlim<TKey, TValue>
.DictionarySlim<TKey, TValue>
is aIDictionary<TKey, TValue>
lightweight implementation that uses a backing array that is faster to a certain point than the default .NetDictionary<TKey, TValue>
.PropertiesDictionary
automatically switches fromDictionarySlim<TKey, TValue>
toDictionary<TKey, TValue>
when the number of properties reaches 6+.CompilationRulesSourceMiddleware
.as
operator (which causes a box conversion) and use explicit cast instead.AggressiveInlining
hint to several methods in order to instruct the JIT to incorporate the annotated methods where they are called.DeferredEval
.MatchOneAsync
to eval rules until the first match (and stops) - starts the evaluation at top or bottom according to thePriorityCriteria
configured.In-memory provider
IEnumerable
with arrays on data models - ensure exact memory allocation and allow usage of fast algorithms to read/write to the data source.IReadOnlyCollection
instead ofIEnumerable
, which favors the use of faster index-based algorithms.Rule
model, and vice-versa.InMemoryRulesStorage
and use specific optimizedList
methods. Also, avoid creatingList
copies.RuleFactory
to not use theRuleBuilder
API and manually build the coreRule
model from data models - this bypasses the validations, which at this point, we assume that the data written to the in-memory data source is correct.MongoDB provider
[BsonElement(Order = <number>)]
.IEnumerable
with arrays on data models - ensure exact memory allocation and allow usage of fast algorithms to read/write to the data source.Rule
model, and vice-versa.DynamicToStrongTypeContentSerializer
due to the same change on the MongoDB driver highlighted above. Adjusted the deserialization according to changes.Benchmark tests
Other tests
Closes #98.
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