Home » Articles » Unique Product Features » Rule Throttling

Rule Throttling

By Mark Joseph - December 17, 2008 @ 10:31 am

This article describes an advanced feature of P6R’s rule engine. (See our XJR SDK.) An introduction to that rule engine can be found at An XPath Enabled Rule Engine. The current article addresses the issue “how effective are my rules”?

Rule Execution Statistics

Passing the ‘P6RULE_KEEPSTATS’ flag into the p6IRuleEngine::initialize() method enables a powerful run-time feature. Automatically a subtree ‘/P6R:stats’ is created (similar to the subtree ‘/P6R:infer’ used to store inferred facts) off of the fact tree. In this tree the following counts are generated: (1) how many times a each rule is executed, and (2) the total number of rules that evaluated to true and those to false. Each count is done in relation to a rule set. After an evaluation this information can be output in a similar way that the inferred rules are output (i.e., p6IRuleEngine::outputStatistics()).

Below is an example output taken from one of our unit tests:

<?xml version="1.0" encoding="utf-8"?>
<P6R:stats xmlns:P6R="http://www.p6r.com/ruleengine">

In the example above, ‘redrover’ is the name of a defined rule set. ‘P6R:defaultset’ is the XML friendly name used for the ‘#default’ rule set. ‘P6R:eval-true’ represents the count of the number of rules that evaluated to true, while ‘P6R:eval-false’ represents the opposite. The ‘newset’ element is a rule in the redrover rule set that ran twice. From these counts we can see what rules get executed and how often.

These counts can be accumulated over one or many p6IRuleEngine::evalute() calls or can be reset at any time by calling the API function p6IRuleEngine::reset( P6RULE_CLEAR_STATS ). Note that these counts are totally separate from the inferred facts that are generated.

One question these counts address is “how effective are my rules”? Clearly if a rule is never executed or runs below expectation that rule likely needs to be changed. Also if the number of rules that evaluate to true seems high then there can a performance issue and the rule set in question may need to be changed (broken up into multiple sets). We added this feature so that developers can get a view into what the rule engine is doing. With these counts rule engine execution its not just a black box.

Now even more interesting is that during rule execution these counts are available for access just like all inferred facts. Since ‘/P6R:stats’ (just like ‘/P6R:infer’) is in the DOM tree all its elements are accessible via XPath. So the value ’2′ of newset can be referenced in a test condition, select attribute, XPath function call etc. This feature allows for all kinds of functionality including “rule throttling”.

Rule Throttling

Lets introduce this topic via a simple example rule:

<rule name='stoprules' setname='redrover'>                   
    <if test='3 < number( /P6R:stats/redrover/newset )' />  
      <set-fact name='infer-end' select='/P6R:stats/redrover/newset' /> 

The above rule tests to see if the newset rule (defined above) has run more than 3 times, and if so places that count as a new inferred fact and then halts rule engine execution. This then controls how many times the newset rule can run. This was meant to be a very simple example, so now lets add some more power to it by changing the ‘test’ attribute to:

<rule name='stoprules' setname='redrover'>                   
    <if test='$g1 < number( /P6R:stats/redrover/newset )' />  
    * * *

Above we have replaced the constant ’3′ with a rule engine variable ‘$g1′. Its important to note that this variable can be defined in the rule set ‘redrover’ or can be a global variable defined and controlled by the application (see An XPath Enabled Rule Engine for a description of this XPath extension mechanism).

This rule engine variable ($g1) can be initialized to a constant, taken from the set of facts, set by another rule, or controlled by an application extension to the rule engine. Its’ value can be set once per evaluation or changed at various times during the same evaluation. This flexibility allows many different ways that rule execution can be “throttled” forward or backwards. For example, an application can create a “feed back” loop where after running one or more evaluations it examines the rule execution statistics (as described above) and based on those numbers change the value assigned to the $g1 global variable. As this value changes so does the value stored in the inferred fact named ‘infer-end’ generated by the ‘stoprules’ rule defined above.

Here is an example of how $g1 can be defined and initialized:

<variable name='$g1' setname='redrover' select='/menu/dessert/item'/>

Assuming that the loaded stated facts has an item at the path /menu/dessert/item.

Here is an example of how the value stored in $g1 can be changed by another rule:

<rule name='change-throttles' setname='redrover'>
  <if test='exists(/P6R:infer/new-rate)'/>                                   
    <set-variable name='$g1' select='/P6R:infer/new-rate' />     
    <set-variable name='$g55' select='55' /> 

The rule ‘change-throttles’ will evaluate to true when a ‘new-rate’ is placed in the inferred facts, and at that time it will change the value of the global variable $g1. Yet this is just one of many examples how such a rule could evaluate to true. The important point here is how the global variable ($g1) can be changed in another rule’s action.

Note, that P6R’s rule engine allows rules to be changed / added / deleted at any time, so the throttle values can also be changed by changing any of these rules directly.

"Rule Throttling" was published on December 17th, 2008 and is listed in Unique Product Features.

Follow comments via the RSS Feed | Leave a comment | Trackback URL

Leave Your Comment