Question

I'm trying to write a C# application that takes in hundreds of thousands of independent rows of data and, based on certain rules defined by a user, sets a certain property. As such I've thought of using a rules engine. After some googling, I decided to use the in-built Windows Workflow Foundation Rules Engine.

The interface for creating the rules is presented to the user in a pipe and filter style:

Raw data -> rule1 -> if result to rule 1 is True, execute rule2 / if result to rule 1 is False, execute rule 3 -> ... branches of execution of other rules ... -> depending on branches taken, property is set to some value.

I wish to be able to execute the rules in a similar pipe and filter / branching style, not sequentially as a non-chaining ruleset does. I am not sure how to create the dependencies for a chaining ruleset to match my flow. I realize WF has IfElse Activities specifically for this type of branching, which support similar rules, but Workflow Activities are two orders of magnitude slower.

Am I using these technologies incorrectly ? (I am new to C#) Should I look into writing my own rule engine ? Any advice is appreciated.

Edit: Additional details about research I've done. I've googled around and read most blog posts / tutorials / msdn resources I could find in the past week (no use linking, there's tons and I used obvious keywords). The rule engine ruleset seems to be exclusively used for sequential independent rules, and when they are dependent, they signal that fact by changing some variable which is a dependency in a rule itself and causes those rules to be re-evaluated (thorough something similar to RETE called full-chaining I believe). I can't see a way of inserting dependencies into my rules dynamically based on their structure and relationship. I can however model this flow of control with IfElse Activities.

I've implemented a small ruleset with 700 rows of sample data and ran a few tests. (no use for pasting in code, I do't have an issue with that) They evaluate in ~50 ms, while the equivalent logic built with IfElse Activities and the same rules evaluates in aprox. 2 seconds, which I am guessing is from the overhead of switching activities. I am either not using these technologies correctly (by which I mean I am not aware of a property of rulesets to be evaluated hierharhically in exclusive branches, or faster switching activities) or there is no easy way to control the flow of execution with just a ruleset and I must therefore incur a large performance penalty with the activities. In which case I might as well write my own rule engine.

Edit 2: A diagram of the flow of execution I need from the ruleset

Was it helpful?

Solution

Right, so I managed to turn the inherent sequential execution of rules into a hierarhical one.

This is achieved by using one additional external variable which serves as the rule id to be next executed, and doubling the number of rules (these extra "execution flow control" rules are hidden from the user). This doubles my execution time, but is still acceptable when compared to using the IfElse Activity. Around 1000000 rows of data can be processed in under a minute.


Structure of a rule :

Rule_n is composed of 2 rules :

Rule_n_1's condition is : RuleIdToBeNextExecuted = n AND (User's rule)

Rule_n_1's Evaluation to True : RuleIdToBeNextExecuted = next action/rule if Rule_n is True

Rule_n_1's Evaluation to False : No action taken.

Rule_n_2's condition is : RuleIdToBeNextExecuted = n AND NOT(User's rule)

Rule_n_2's Evaluation to True : RuleIdToBeNextExecuted = next action/rule if Rule_n is False

Rule_n_2's Evaluation to False : No action taken.


Equivalent diagram to the one in the question : More states

This structure allows me to create a pipe&filter execution approach to the user's rules.

Research : My own data structure design.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top