65873 members! Sign up to stay informed.

Sponsored Links


Resources

.NET Research Library
Get .NET related white papers, case studies and webcasts

News News News Messages: 30 Messages: 30 Messages: 30 Printer friendly Printer friendly Printer friendly Post reply Post reply Post reply XML XML XML

TechTalk: Scott Woodgate Talks About BizTalk Server 2004 & 2006

Posted by: Paul Ballard on August 24, 2005 DIGG
Scott Woodgate, Group Product Manager for BizTalk Server talks about the evolution of BizTalk Server and how it addresses the requirements of an Enterprise Service Bus. He also talks about BizTalk Server 2006's focus on administration and deployment and new features that make those efforts easier. He also describes the Rules Engine in BizTalk Server in some detail.
And so these messaging based systems were good for getting customers started with connecting applications together, but they were really looking to add some more value into what they were doing by putting a business process on top of it. So, it’s not just Seibel talking to SAP, but it’s a conversation where Seibel and SAP talk because I receive a purchase order from trading partner that goes into my Seibel application, does a lookup on some employee information, comes back to my SAP system, does a lookup on some price and so on. So that business process functionality is something that everybody was really keen for us to improve on in BizTalk Server 2004. That was the number one investment we made in 2004.
When asked about how BizTalk Server could be used as an Enterprise Service Bus, Scott clearly positions BizTalk Server as Microsoft's answer to ESB.
And the first thing I want to say is, if you're a developer, architect or customer and you’ve been considering enterprise service bus because you have been talking to one of key analysts like Gartner or one of our competitors, then Microsoft can absolutely offer enterprise service bus capabilities. The combination of BizTalk Server and web services stack today offers that and then BizTalk Server and Indigo in 2006 timeframe really compete the web services stack.
The discussion then moves to BizTalk Server's Rules Engine and how it compares to other rules processing systems in the industry.
Of course, it needs to be economical relative to other rules engines and I think our low-end edition, Partner Edition, which includes the rules engine and only costs a thousand US dollars is incredibly economical relative to competitive offering in the rules engine space.
Watch Scott Woodgate on BizTalk Server 2004 & 2006

Threaded replies

·  TechTalk: Scott Woodgate Talks About BizTalk Server 2004 & 2006 by Paul Ballard on Wed Aug 24 11:39:55 EDT 2005
  ·  A challenge to Microsoft by peter lin on Thu Aug 25 20:21:52 EDT 2005
    ·  A challenge to Microsoft by Andrew Bryson on Fri Aug 26 12:50:28 EDT 2005
    ·  So Detective ... by Kevin Lewis on Fri Aug 26 14:38:03 EDT 2005
      ·  So Detective ... by peter lin on Fri Aug 26 15:11:59 EDT 2005
        ·  Conclusion by Kevin Lewis on Fri Aug 26 15:21:20 EDT 2005
          ·  you're right by peter lin on Fri Aug 26 16:58:45 EDT 2005
            ·  oops typo by peter lin on Fri Aug 26 17:02:12 EDT 2005
  ·  here is the link by peter lin on Fri Aug 26 15:19:39 EDT 2005
  ·  More evidence by peter lin on Sat Aug 27 18:37:30 EDT 2005
  ·  Other odd behavior by peter lin on Mon Aug 29 18:06:13 EDT 2005
  ·  Does no comment from Microsoft mean it's not RETE? by peter lin on Tue Aug 30 20:37:24 EDT 2005
    ·  Yes it is Rete!! by Charles Young on Thu Sep 01 13:39:19 EDT 2005
      ·  Are you sure? by peter lin on Thu Sep 01 18:01:08 EDT 2005
        ·  Yes I am. by Charles Young on Thu Sep 01 22:34:10 EDT 2005
          ·  Good points by peter lin on Fri Sep 02 00:17:13 EDT 2005
            ·  corrections to my post by peter lin on Fri Sep 02 20:25:06 EDT 2005
            ·  What I think happened...and other matters by Charles Young on Sun Sep 04 18:49:42 EDT 2005
              ·  What I think happened...and other matters by peter lin on Sun Sep 04 20:04:15 EDT 2005
                ·  link to screen capture by peter lin on Sun Sep 04 20:05:38 EDT 2005
                  ·  An interesting paper... by Charles Young on Mon Sep 05 14:46:07 EDT 2005
                    ·  An interesting paper... by peter lin on Mon Sep 05 19:02:44 EDT 2005
                ·  Jess, Drools and MS-BRE comparison by Charles Young on Fri Sep 16 00:27:35 EDT 2005
                  ·  Typo alert... by Charles Young on Fri Sep 16 03:48:15 EDT 2005
                    ·  Further results by Charles Young on Tue Sep 20 17:37:07 EDT 2005
                      ·  thanks to Mr Young by peter lin on Wed Sep 21 17:27:37 EDT 2005
      ·  Clarification by peter lin on Thu Sep 01 21:59:45 EDT 2005
  ·  from Forgy's paper by peter lin on Thu Sep 01 20:32:49 EDT 2005
  ·  Looks like global bindings by peter lin on Tue Sep 06 15:18:40 EDT 2005
  ·  more food for thought by peter lin on Sun Sep 11 00:35:22 EDT 2005
    ·  Its a rule 'term', not an engine function by Charles Young on Thu Sep 15 22:07:16 EDT 2005
  Message #182534 Post reply Post reply Post reply Go to top Go to top Go to top

A challenge to Microsoft

Posted by: peter lin on August 25, 2005 in response to Message #182318
And now, you can put those inside a forward chaining RETE based rules engine and that rules engine then goes ahead and executes the rules and there is a user interface that you can use, or you can create your own as a developer to go ahead and make that easy for people to create rules out of your own web pages to ASP.NET or through a designer that we provide.

Once again, I think Microsoft is making claims that are clearly untrue. If the biztalk rule engine really implemented RETE algorithm as Dr. Forgy described in his two papers, the performance characteristics would not show a dramatic decrease in performance as the number of rules increase.

Just to be totally clear. RETE when implemented correctly will not show a 2x decrease in performance as the rule count increases 2x. The performance numbers published by microsoft shows the performance decreases more than 2x as the ruleset size increases 2x. The performance with respect to rulset (ie number of rules) size is directly the result of the algorithm implemented. There have been implementations in C, C++, Lisp, smalltalk, and Java. None of the existing RETE engines I know of show such poor performance with respect to ruleset size.

The only way a rule engine would exhibit the performance characteristics shown by Biztalk rule engine, is if the implementation is a simple forward chaining engine without being full RETE. That's a very easy mistake to make, but Microsoft needs to prove Biztalk rule engine implements RETE. Making claims of RETE when their performance clearly shows it isn't shows a lack of integrity from Microsoft. It is also illegal to make false claims.

Anyone can easily see this by running a series of performance tests with 10, 50, 100, 500, 1000 rules with CLIPS (written in C), JRules for .NET (.NET) or JESS (Java) The expected performance should show a 2x decrease in performance (activations/second) when the ruleset size increases 4-5x for simple rules without joins.

peter lin

  Message #182631 Post reply Post reply Post reply Go to top Go to top Go to top

A challenge to Microsoft

Posted by: Andrew Bryson on August 26, 2005 in response to Message #182534
Interesting comment, Peter. I look forward the MS response. I'm curious as to where you found the document illustrating performance benchmarks for the BTS RE.

  Message #182650 Post reply Post reply Post reply Go to top Go to top Go to top

So Detective ...

Posted by: Kevin Lewis on August 26, 2005 in response to Message #182534
So you're saying that there is no way they could be telling the truth about RETE and BizTalk? There is no scenario that would lead to the kind of performance degradation you describe? I would think that such conclusions would require a detailed knowledge of the BizTalk implementation. Do you have that knowledge?

Or are you saying that because other rules engines that you do consider to be RETE "compliant" perform as you expect, all such engines must perform similarly? There’s no possibility, none, that other features that span the implementation might cause the performance characteristics to be different?

I personally find your conclusions just a bit of a jump. But maybe you have much better evidence than you've exposed here.

  Message #182655 Post reply Post reply Post reply Go to top Go to top Go to top

So Detective ...

Posted by: peter lin on August 26, 2005 in response to Message #182650
So you're saying that there is no way they could be telling the truth about RETE and BizTalk? There is no scenario that would lead to the kind of performance degradation you describe? I would think that such conclusions would require a detailed knowledge of the BizTalk implementation. Do you have that knowledge?Or are you saying that because other rules engines that you do consider to be RETE "compliant" perform as you expect, all such engines must perform similarly? There’s no possibility, none, that other features that span the implementation might cause the performance characteristics to be different?I personally find your conclusions just a bit of a jump. But maybe you have much better evidence than you've exposed here.

There are only a few ways to implement RETE. Usually, this kind of performance is the result of mis-interpreting RETE and not implementing the joins and indexes correctly. There are a couple of things a RETE engine must have to be considered RETE.

1. implement alpha node, which compares values, like object.attr1 == "hello"
2. implement beta node, which compares object fields, like object1.attr2 == object3.attr5
3. implement an index for all alpha nodes
4. implement an index for all beta nodes
5. join nodes sequentially. Say I have a rule that uses 3 objects, obj1, obj2, obj3. With the following rule
if
  obj1.attr1 == 1, obj1.attr3 == "hello" (pattern 1)
  obj3.attr3 bound to var myvar0, obj3.attr1 == 100 (pattern 2)
  obj2.attr2 bound to var myvar1 (pattern 3)
  myvar0 == myvar1 (pattern 4)
then
  do something
in this rule, the first join is between pattern 1 and 2, followed join 2 & 3, then the forth join node compares the bound variables.
6. implement an agenda where activations are placed
7. implement conflict resolution strategy
8. implement input node (one per object type)
9. implement terminal node
10. implement a working memory

Having said that, the kind of performance shown by Biztalk in the numbers published by MS on MSDN shows greater than 2x decrease in performance for simple rules without any joins. You can search for bizalk threads on TSS.net and find the link.

This kind of performance characteristics is usually the result of not implementing either alpha or beta memory. Which would mean Biztalk's rule engine is just a chaining rule engine. To qualify as RETE, it has at minimum meet the requirements I listed. Even a bad implementation of RETE would display better performance as ruleset size increases. Just to be totally clear. I'm not comparing different engines. I speaking primarily of the performance of the engine as the number of rules increase.

The primary benefit of RETE algorithm is the performance is not dependent on the number of rules. Here are some links for those who want to read for themselves.

http://herzberg.ca.sandia.gov/jess/docs/52/rete.html
http://en.wikipedia.org/wiki/Rete_algorithm
http://www.ghg.net/clips/download/documentation/

Don't take my word for it. See for youself. I'm no expert. Even with my limited knowledge, it's clear Biztalk's rule engine does not implement RETE.

peter

  Message #182658 Post reply Post reply Post reply Go to top Go to top Go to top

here is the link

Posted by: peter lin on August 26, 2005 in response to Message #182318
here is an old like posted by Scott Woodgate on TSS.net

http://www.gotdotnet.com/team/wsservers/bts2004/BTS2004Performance.zip

look at those numbers and you'll see

peter

  Message #182659 Post reply Post reply Post reply Go to top Go to top Go to top

Conclusion

Posted by: Kevin Lewis on August 26, 2005 in response to Message #182655
What I'm trying to point out is, even if there's some doubt that BizTalk is fully RETE, to say that it definitively is not, simply from circumstantial evidence, is a little presumptuous.

Rather, if there is some question, let's try to get Microsoft to answer instead of calling them a bunch of liars. It may be that you're right. It may also be that there is anther good reason for the seeming disparity of facts.

I'm not saying you can always believe Microsoft market droids, but their technical people usually shoot straight (in my experience, anyway--maybe your experience is different).

  Message #182680 Post reply Post reply Post reply Go to top Go to top Go to top

you're right

Posted by: peter lin on August 26, 2005 in response to Message #182659
What I'm trying to point out is, even if there's some doubt that BizTalk is fully RETE, to say that it definitively is not, simply from circumstantial evidence, is a little presumptuous.

Rather, if there is some question, let's try to get Microsoft to answer instead of calling them a bunch of liars. It may be that you're right. It may also be that there is anther good reason for the seeming disparity of facts.I'm not saying you can always believe Microsoft market droids, but their technical people usually shoot straight (in my experience, anyway--maybe your experience is different).

You're right. I have no proof their implementation is RETE or not. But think of it another way.

1. a full RETE implementation exhibits performance which is not dependent on the number of rules

2. non-RETE implementation exhibit the type of performance documented by Microsoft.

I agree Microsoft could have implemented RETE, but done it in such an aweful way that performance is bad and scalability terrible. I find that very unlikely. It's possible, but highly unlikely to me.

According to Microsoft, they started the project in 2000. That means they had plenty of time to do a good implementation. From first hand experience writing rule engines and building applications using rule engines, it's more likely than not the developers mis-interpreted forgy's paper.

Having read part of Forgy's 1978-79 paper and his second RETE paper several dozen times, it is not the easiest algorithm to understand. In fact, it's very hard to understand and counter to normal programmer intuition. Having said that, I expect microsoft to perform due diligence and verify their implementation is RETE. Given the performance of Biztalk rule engine do not match the claims of RETE, it should have been a huge red flag.

then again, I could be wrong and microsoft could have chosen the easy way out and decided it was more important to get something out and worry about making it RETE in 10-15 years. I've challenged Microsoft in the past to back up their claims, but so far they haven't. I will gladly apologize to microsoft and the biztalk team as soon as they prove BRE really implements RETE.

My concern is that Microsoft is giving RETE a bad name, since BRE clearly doesn't perform as RETE algorithm predicts. Therefore, the ethical thing to do is to simply claim BRE is a forward chaining rule engine and claim something that is clearly questionable.

peter

  Message #182682 Post reply Post reply Post reply Go to top Go to top Go to top

oops typo

Posted by: peter lin on August 26, 2005 in response to Message #182680
Therefore, the ethical thing to do is to simply claim BRE is a forward chaining rule engine and claim something that is clearly questionable.peter

meant to say, microsoft can cleanly claim forward chaining without claiming RETE. especially when their own benchmarks prove BRE doesn't scale as RETE algorithm predicts.

peter

  Message #182737 Post reply Post reply Post reply Go to top Go to top Go to top

More evidence

Posted by: peter lin on August 27, 2005 in response to Message #182318
For those who haven't looked at Biztalk's Rule Engine, here are some links.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sdk/htm/ebiz_prog_rules_rgxf.asp
Side effects

The second link describes side effects of altering an object during the reasoning process. That is a huge clue that BRE is not RETE, because it means the rule engine is using the objects directly. To put it in plain english, it does NOT implement a working memory. The result of this design choice is BREW cannot gaurantee the truthfullness of the results. There is a concept in the inference engine domain called "truth maintenance". Basically, it is this.

The rule engine must evaluate all facts asserted to the working memory and re-evaluate any changes which occurred during the reasoning process. This insures that any activations in the agenda which are no longer valid are removed. It also insures that the results are accurate. Without a working memory, it's very hard to gaurantee the results are accurate. Not having a working memory also indicates BRE does not implement both alpha and beta memory.

No one should take my word for it. Read the references I included in previous posts and decide for yourself.

peter

  Message #182889 Post reply Post reply Post reply Go to top Go to top Go to top

Other odd behavior

Posted by: peter lin on August 29, 2005 in response to Message #182318
Someone asked me recently why they see odd and unpredictable behavior in biztalk's rule engine. My guess is the fantom behavior is because BRE uses the objects directly, rather than creating "shadown facts". This goes against standard inference engine design and implementation. Without truth maintenance, it's just a rule engine and not an inference engine.

peter lin

  Message #183033 Post reply Post reply Post reply Go to top Go to top Go to top

Does no comment from Microsoft mean it's not RETE?

Posted by: peter lin on August 30, 2005 in response to Message #182318
Since there is no response from Microsoft, I'm going assume Microsoft has no proof of RETE, other than a lot of "hot air". I hope all customers using biztalk's rule engine calls Microsoft and asks for a full explanation. I spent some time looking at the variou public API, docs, examples and articles and it's pretty clear the design is the following.

1. XPath is used to denote a leaf node. A leaf node in this case would be a comparison of an (object.field operator value).
2. the value stored with the key performs the actual evaluation
3. a HashMap is used to store the keys and leaf nodes. in other words key=XPath, value=leaf node.
4. direct memory is used, instead of shadow facts like JESS, JRules and other mature RETE engines. This means it does not support "truth maintenance" and requires developers manually keep track of modifications. This is referred to as "side effects" in biztalk documentation.
5. direct memory is not the same as the working memory described by Dr. forgy.
6. using a HashMap centric design, it most likely does not store alpha and beta memory.
7. some one told me biztalk rule engine implements CF, which I am guessing is "certainty factor." Here is a link on CF http://www.amzi.com/ExpertSystemsInProlog/03backwarduncertainty.htm#determiningpremisecf
8. implementing CF does not make any sense for strict RETE rule engines, since RETE over comes the limitations of early non-RETE inference engines for Prolog. here is a link http://www.amzi.com/ExpertSystemsInProlog/. Here is a paragraph from the site, which explains things pretty clearly.
The match algorithm used in the first implementation of Foops takes every rule and compares it to all the frame instances on each cycle. In particular, both of the example rules above would be compared against working storage on each cycle. Not only is redundant matching being done on each cycle, within each cycle the same frame patterns are being matched twice, once for each rule. Since working memory generally has few changes on each cycle, and since many of the rules have redundant patterns, this approach is very inefficient.

With the Rete algorithm, the status of the match information from one cycle is remembered for the next. The indexing allows the algorithm to update only that match information which is changed due to working memory changes.

The rules are compiled into a network structure where the nodes correspond to the frame patterns in the LHS of the rules. There are three basic types of node which serve as: the entry to the network; the internals of the network; and the exit from the network. These are called root nodes, two-input nodes, and rule nodes respectively.

There are serious draw backs of using non-RETE algorithms, like using a XPath approach.

1. as rule complexity increases, with either greater number of conditions or joins, the performance will decrease exponentially.
2. there is a direct relationship between the number of rules and decrease in performance
3. any fact modification during the reasoning cycle also incures a serious impact on performance

It's rather easy to prove this. All one has to do is load a dozen or so rules and profile the rule engine. What you'll see is the rule engine iterates over all the keys when a modified fact is retract and then re-asserted. I don't plan on doing this, since I don't have a license of Biztalk. If anyone tries it, I would like to hear about the results.

peter

  Message #183309 Post reply Post reply Post reply Go to top Go to top Go to top

Yes it is Rete!!

Posted by: Charles Young on September 01, 2005 in response to Message #183033
Peter

I've been meaning to weigh into this argument for several months or at least get round to blogging on the Rules Engine in some depth. I don't particularly want to start some 'war' on this subject, but your comments cannot remain unchallenged any longer.

First to state my 'credentials'. I'm not, and never have been, a Microsoft employee. I do, however, work for a Microsoft Gold Partner company that specialises principally in BizTalk development, and I have personally been using BizTalk Server 2004 continually for almost two years (since beta). I also arguably have the best knowledge of the Rules Engine amongst my immediate colleagues, though I don't pretend to rival your experience of implementing Rete-based engines. I am not speaking on behalf of Microsoft, either officially or unofficially. Indeed, I have not discussed this reply with anyone in my own company, let alone Microsoft.

Rete algorithm
I think it should be noted that Scott Woodgate, who is the programme manager for BizTalk, stated very clearly, some months ago in this same forum, that the BizTalk engine implements the Rete algorithm. The Business Rules Framework team is quite separate to the BizTalk team, and Scott is not really a techie, but nevertheless, Microsoft has responded previously to your questions and claims.

For my part, I can assure you, with all the authority I can muster on this subject, and without any equivocation, that the Microsoft Rules Engine is 100% based on the Rete algorithm. It represents a particularly straight-forward 'text-book' implementation of the algorithm, without any notable elaboration or deviation (Scott's comments about some optimisations are all very straightforward, and do not affect the core implementation of the algorithm in any way). The implementation includes everything you would expect, including alpha and beta memory, root, condition, join and terminal nodes, an agenda, conflict resolution and working memory. The engine is rather un-adventurous, in that it supports only a single, salience-based, conflict resolution policy. How do I know all this - well...a techie's fascination with how things work coupled with a bit too much time spent with a reflector tool.

Side effects

I was particularly concerned to read your beliefs on how the engine is implemented. This is not accurate in any respect, although you do raise one significant issue with regard to 'side effects'. Unfortunately, your conclusion that "This means [the engine] does not support "truth maintenance" and requires developers manually keep track of modifications." is very incorrect. However, as the documentation on side effects is partial, minimal and fairly impenetrable, I can understand the confusion.

Before explaining, let me get one issue out of the way. I have seen no evidence of a non-monotonic CF approach, and am quite certain that this is not used by the engine. On the contrary. The engine uses the classic Rete approach, storing partial match results in beta memory.

As you have surmised, the side-effects feature could potentially 'compromise' truth maintenance to a degree. However, Microsoft has adopted other strategies within their technology which mitigate or remove this risk in most scenarios, and by default, they only allow the risk in a limited set of scenarios for some very good and practical reasons. I would certainly want to criticise Microsoft for their failure to properly document this, and I have a few minor concerns about some of the exact mechanics of how they have implemented their side-effects feature, but broadly, their approach is sensible and reasonable.

Microsoft supports three different 'media' for representing and asserting facts to the engine. Facts can be asserted as .NET objects, XML documents or ADO.NET datasets (a dataset is essentially an in-memory relational data cache). Internally, the engine further abstracts facts in two ways. Firstly, it wraps XML documents and dataset objects in specialised 'wrapper' classes (rather like shadow facts). Secondly, and more importantly for the purposes of this discussion, it abstracts all facts within the working memory using instances of a class called 'WorkingMemoryElement' (they couldn't have been any more 'text-book' than this). All the stuff you wrote about XPath and leaf nodes is entirely wrong in relation to the engine. In effect, WorkingMemoryElement lies at the centre of a typical head/slot representation of facts.

The 'side effects' feature refers to a simple read-only cache feature associated with WorkingMemoryElement. This cache is optionally used during slot evaluation. The 'sideeffects' flag which controls this is set (via Microsoft XML rule language) on each slot evaluation within conditions and actions. If switched on, the cache is not used - i.e., WorkingMemoryElement goes back to the underlying fact object to get the datum. If switched off, the WorkingMemoryElement caches the value on the first read, and uses the cache thereafter.

By default, 'side effects' is only switched on for slots backed by .NET object facts. It is switched off for XML and dataset facts. There is a very good reason for this. In order to support its generic abstraction of facts internally, the engine uses reflection to invoke members of underlying 'fact' objects (remember the engine uses wrapper classes for XML and datasets). For facts asserted as .NET objects, the engine invokes methods and properties (.NET's higher-level abstraction of accessor methods) using this single mechanism. This means that the engine can evaluate members that execute code. If side effects is switched off, code will only be invoked the first time the slot (which maps to the object member) is evaluated. By adopting the default of switching side effects on, Microsoft ensures that the code in the underlying .NET object is invoked on each evaluation.

For XML and dataset facts, side effects is switch off. More than that, the flag appears always to be ignored when evaluating an XML or dataset-backed slot within a condition (this is entirely undocumented!). Hence, issues only arise when asserting .NET objects as facts. You could debate Microsoft's default approach endlessly, but for my part, I think their decision to switch side effects on for .NET objects is sensible and defensible. Novice users would be very confused by the alternative approach, and experienced users can always switch the side-effects feature off.

Microsoft has reduced the risk further through another mechanism whereby, generally, asserts, updates and retracts (I won't explain the finer points of an 'update' here, but Microsoft's implementation is quite interesting) are only performed once all other actions in a rule have been completed (including any evaluations of slots within the action list). It does this regardless of where asserts, etc., appear in the action list. This makes sense in the vast majority of scenarios, although a knowledgeable developer can invoke asserts, etc., (and hence enter a new match-resolve-act cycle) midway through the action list if they really want to. This is a documented feature (just), and helps to reduce the risks associated with using the side effects feature.

The real issue here is that there is an impedance between the OO model represented by .NET objects and the head/slot model typically used in Rete-based engines. Microsoft allows developers to exploit the rich OO model directly within their rules without any particular restriction, but this means that they map 'slots' not only to accessor methods, but also to other methods including voids and static members. I love this feature, but also recognise that it can (and often does) lead to a somewhat 'impure' approach where business logic is deeply integrated with asserted facts. This is very practical and flexible when dealing with business rules, but maybe not designed to appeal to the AI purists amongst us.

It's worth mentioning something about shadow facts here. I've only come across the term 'shadow facts' in Jess. In this case, shadow facts essentially wrap Java Bean components (a bit like Microsoft wrapping XML DOM document and ADO.NET dataset objects) and can optionally use PropertyChangeListeners to update working memory with changes to bean state. Because the .NET object approach is not targeted to a specific component model, there is no equivalent of Jess' PropertyChangeListener approach, but there again, this feature is not needed if side effects is switched on.

Performance

This must, of necessity, be the weakest part of my reply because I do not have comparative facts and figures to prove/disprove your assertions about performance. I did implement the Miss Manners benchmark (traditional 8-rule version) a little while back, and I have run some entirely informal and non-trustworthy tests against a very similar implementation for an open-source Java-based Rete engine. The Microsoft engine 'won' in this case, but given the way benchmarks are treated, I am not willing at this time to publish my 'results', or even to say which engine I ran the tests against. Suffice to say that my informal testing suggested that the Microsoft engine is really quite efficient.

Your specific issue is with some figures published in a Microsoft whitepaper. If I get time in the next few weeks, I might see if I can shed further light on the alleged performance degradation when increasing the number of rules. The whitepaper does not provide any great detail on exactly how the measure was made. The paper was, I presume, written by members of the BizTalk team. this team was not responsible for the rules engine, and wouldn't necessary be aware of the finer points of Rete performance (the author may never even have heard of Rete). They are measuring enormous rulesets containing between 1,000 and 10,000 rules. There is plenty of scope here for significant misinterpretation of what the figures are telling us, and to base such a sustained attack on Microsoft's engine on the basis of a couple of graphs is really not, in my opinion, very wise. Still, I understand the concern. If I get time I will look into this issue further.

If you are interested in getting your hands on the rules engine, you could always download the 120-day evaluation copy of BizTalk from the Microsoft web site at:

http://www.microsoft.com/biztalk/evaluation/trial/default.mspx)

  Message #183335 Post reply Post reply Post reply Go to top Go to top Go to top

Are you sure?

Posted by: peter lin on September 01, 2005 in response to Message #183309
First off, thanks for responding. It's clear you have a lot of experience with Biztalk's rule engine, but some of your response does not fit established RETE practices and concepts. My hope was to get more details from Microsoft about the rule engine, but I'll settle for any good response.
PeterI've been meaning to weigh into this argument for several months or at least get round to blogging on the Rules Engine in some depth. I don't particularly want to start some 'war' on this subject, but your comments cannot remain unchallenged any longer.First to state my 'credentials'. I'm not, and never have been, a Microsoft employee. I do, however, work for a Microsoft Gold Partner company that specialises principally in BizTalk development, and I have personally been using BizTalk Server 2004 continually for almost two years (since beta). I also arguably have the best knowledge of the Rules Engine amongst my immediate colleagues, though I don't pretend to rival your experience of implementing Rete-based engines. I am not speaking on behalf of Microsoft, either officially or unofficially. Indeed, I have not discussed this reply with anyone in my own company, let alone Microsoft.

Rete algorithm I think it should be noted that Scott Woodgate, who is the programme manager for BizTalk, stated very clearly, some months ago in this same forum, that the BizTalk engine implements the Rete algorithm. The Business Rules Framework team is quite separate to the BizTalk team, and Scott is not really a techie, but nevertheless, Microsoft has responded previously to your questions and claims.

You're absolutely right. Scott Woodgate did state clearly, he believed it is RETE. I am simply challenging the claim, since my knowledge of RETE rule engines at the lowest level tells me the performance doesn't match the predicted results.
For my part, I can assure you, with all the authority I can muster on this subject, and without any equivocation, that the Microsoft Rules Engine is 100% based on the Rete algorithm. It represents a particularly straight-forward 'text-book' implementation of the algorithm, without any notable elaboration or deviation (Scott's comments about some optimisations are all very straightforward, and do not affect the core implementation of the algorithm in any way). The implementation includes everything you would expect, including alpha and beta memory, root, condition, join and terminal nodes, an agenda, conflict resolution and working memory. The engine is rather un-adventurous, in that it supports only a single, salience-based, conflict resolution policy. How do I know all this - well...a techie's fascination with how things work coupled with a bit too much time spent with a reflector tool.Side effectsI was particularly concerned to read your beliefs on how the engine is implemented. This is not accurate in any respect, although you do raise one significant issue with regard to 'side effects'. Unfortunately, your conclusion that "This means [the engine] does not support "truth maintenance" and requires developers manually keep track of modifications." is very incorrect. However, as the documentation on side effects is partial, minimal and fairly impenetrable, I can understand the confusion.

The reason I challenge microsoft is that those with no experience with RETE will think "side effects" are the product of RETE. Clearly, no strict RETE implementation exhibits what microsoft calls "side effects". Anyone can verify that by looking at JRules, JESS, clips, Blaze, etc.
Before explaining, let me get one issue out of the way. I have seen no evidence of a non-monotonic CF approach, and am quite certain that this is not used by the engine. On the contrary. The engine uses the classic Rete approach, storing partial match results in beta memory.As you have surmised, the side-effects feature could potentially 'compromise' truth maintenance to a degree. However, Microsoft has adopted other strategies within their technology which mitigate or remove this risk in most scenarios, and by default, they only allow the risk in a limited set of scenarios for some very good and practical reasons. I would certainly want to criticise Microsoft for their failure to properly document this, and I have a few minor concerns about some of the exact mechanics of how they have implemented their side-effects feature, but broadly, their approach is sensible and reasonable. Microsoft supports three different 'media' for representing and asserting facts to the engine. Facts can be asserted as .NET objects, XML documents or ADO.NET datasets (a dataset is essentially an in-memory relational data cache).
I am a bit puzzled by that statement. A strict RETE implementation must always make a copy of data be it XML, datasets or anything else asserted to the working memory. Without that, there is no gaurantee some other process hasn't altered a fact. That's a critical concept. If a rule engine were to assert objects without making a shadow copy, it must lock that data and prevent it from being modified. If it does not, it will see "phantom" behavior. These concepts have been around for over a decade in the rule engine world and isn't new.
Internally, the engine further abstracts facts in two ways. Firstly, it wraps XML documents and dataset objects in specialised 'wrapper' classes (rather like shadow facts). Secondly, and more importantly for the purposes of this discussion, it abstracts all facts within the working memory using instances of a class called 'WorkingMemoryElement' (they couldn't have been any more 'text-book' than this). All the stuff you wrote about XPath and leaf nodes is entirely wrong in relation to the engine. In effect, WorkingMemoryElement lies at the centre of a typical head/slot representation of facts.
this statement confuses me. in RETE there is no "head/slot". Are you refering to slotname and value? for example, in clips one might have:
(myobject
  (attr1 "new")
  (attr3 100)
)
In strict RETE, all comparisons of an object.field to a concrete value is converted to an Alpha node. That alpha node is responsible for remembering what facts matched and creating an index. A alpha node knows it's successors, but it does not know it's predacessor. Don't take my word for it, look at how CLIPS implements it.
The 'side effects' feature refers to a simple read-only cache feature associated with WorkingMemoryElement. This cache is optionally used during slot evaluation. The 'sideeffects' flag which controls this is set (via Microsoft XML rule language) on each slot evaluation within conditions and actions. If switched on, the cache is not used - i.e., WorkingMemoryElement goes back to the underlying fact object to get the datum. If switched off, the WorkingMemoryElement caches the value on the first read, and uses the cache thereafter.
Again, this type of design goes against RETE's concept of a self contained working memory, which is under the control fo the rule engine. Any form of working memory that does not follow that design is not strict RETE.
By default, 'side effects' is only switched on for slots backed by .NET object facts. It is switched off for XML and dataset facts. There is a very good reason for this. In order to support its generic abstraction of facts internally, the engine uses reflection to invoke members of underlying 'fact' objects (remember the engine uses wrapper classes for XML and datasets).
I'm familiar with this approach and numerous others have tried direct memory. Most of them eventually realized creating a copy of the original object instance is the best way. I would suggest looking at Drools rule engine. The current release does the same thing. It wraps the objects and gets the value when needed.
For facts asserted as .NET objects, the engine invokes methods and properties (.NET's higher-level abstraction of accessor methods) using this single mechanism. This means that the engine can evaluate members that execute code. If side effects is switched off, code will only be invoked the first time the slot (which maps to the object member) is evaluated. By adopting the default of switching side effects on, Microsoft ensures that the code in the underlying .NET object is invoked on each evaluation.
The problem is, what happens when the value changes the third time the object.field is evaluated? The results are no longer true. What's worse is if there's not standard mechanism for notifying the rule engine, it's nearly impossible for a novice to track down the cause. Others will disagree, but it's a naive design choice. That design means the rule engine is only "good" for cases where data is static and does not change.
For XML and dataset facts, side effects is switch off. More than that, the flag appears always to be ignored when evaluating an XML or dataset-backed slot within a condition (this is entirely undocumented!). Hence, issues only arise when asserting .NET objects as facts. You could debate Microsoft's default approach endlessly, but for my part, I think their decision to switch side effects on for .NET objects is sensible and defensible. Novice users would be very confused by the alternative approach, and experienced users can always switch the side-effects feature off. Microsoft has reduced the risk further through another mechanism whereby, generally, asserts, updates and retracts (I won't explain the finer points of an 'update' here, but Microsoft's implementation is quite interesting) are only performed once all other actions in a rule have been completed (including any evaluations of slots within the action list). It does this regardless of where asserts, etc., appear in the action list. This makes sense in the vast majority of scenarios, although a knowledgeable developer can invoke asserts, etc., (and hence enter a new match-resolve-act cycle) midway through the action list if they really want to.
This type of behavior is sometimes called "lazy evaluation". In other words, process all actions of a rule (aka right-hand side) and place them in a queue. Once all activations are processed, execute each update sequentially. CLIPS implements a form of this.
This is a documented feature (just), and helps to reduce the risks associated with using the side effects feature.The real issue here is that there is an impedance between the OO model represented by .NET objects and the head/slot model typically used in Rete-based engines. Microsoft allows developers to exploit the rich OO model directly within their rules without any particular restriction, but this means that they map 'slots' not only to accessor methods, but also to other methods including voids and static members. I love this feature, but also recognise that it can (and often does) lead to a somewhat 'impure' approach where business logic is deeply integrated with asserted facts.
All the major rule engines have these capabilities. In JESS one can mix Objects with deftemplates. Same is true of other mature rule engiens.
This is very practical and flexible when dealing with business rules, but maybe not designed to appeal to the AI purists amongst us. It's worth mentioning something about shadow facts here. I've only come across the term 'shadow facts' in Jess. In this case, shadow facts essentially wrap Java Bean components (a bit like Microsoft wrapping XML DOM document and ADO.NET dataset objects) and can optionally use PropertyChangeListeners to update working memory with changes to bean state.
That is incorrect. JESS makes a copy of the object and links the two. When an object is asserted in JESS, the engine copies the values to the corresponding deftemplate. All major rule engines do this. The first thing JESS does is add itself as a listener using propertyChangeListener. It then makes a copy. Objects can be asserted as static or dynamic. If an object is static, JESS ignores the changes.
Because the .NET object approach is not targeted to a specific component model, there is no equivalent of Jess' PropertyChangeListener approach, but there again, this feature is not needed if side effects is switched on. Performance
This must, of necessity, be the weakest part of my reply because I do not have comparative facts and figures to prove/disprove your assertions about performance. I did implement the Miss Manners benchmark (traditional 8-rule version) a little while back, and I have run some entirely informal and non-trustworthy tests against a very similar implementation for an open-source Java-based Rete engine. The Microsoft engine 'won' in this case, but given the way benchmarks are treated, I am not willing at this time to publish my 'results', or even to say which engine I ran the tests against. Suffice to say that my informal testing suggested that the Microsoft engine is really quite efficient.
If you aren't comfortable posting your results, would you consider sending them to me? I curious, did you compare it to Drools? The reason I ask is that Drools current implementation is only forward chaining with arbitrary joins. That result in a huge slow down as the number of guests increases. I wrote a clean implementation of RETE from scratch and gave it to Drools.
Your specific issue is with some figures published in a Microsoft whitepaper. If I get time in the next few weeks, I might see if I can shed further light on the alleged performance degradation when increasing the number of rules. The whitepaper does not provide any great detail on exactly how the measure was made. The paper was, I presume, written by members of the BizTalk team. this team was not responsible for the rules engine, and wouldn't necessary be aware of the finer points of Rete performance (the author may never even have heard of Rete). They are measuring enormous rulesets containing between 1,000 and 10,000 rules. There is plenty of scope here for significant misinterpretation of what the figures are telling us, and to base such a sustained attack on Microsoft's engine on the basis of a couple of graphs is really not, in my opinion, very wise.
I generated simple rules like the ones in the Biztalk document and ran the benchmark in JESS. My results showed that JESS performance only decreases 4x when the ruleset size creased from 1k-10K (1 order of magnitude). Since you've read the performance document, you can see it clearly doesn't perform that way for simple rules with 1-2 conditions.
Still, I understand the concern. If I get time I will look into this issue further.If you are interested in getting your hands on the rules engine, you could always download the 120-day evaluation copy of BizTalk from the Microsoft web site at:http://www.microsoft.com/biztalk/evaluation/trial/default.mspx)

I honestly believe Microsoft believes it implemented RETE. What I don't believe is that they really did. I say this from first hand experience writing rule engines. If Biztalk rule engine really implements RETE, what you'll see in a profiler is it should

1. create n alpha nodes for n unique conditions. more if it doesn't implement node sharing or if the rules are written in such a way that node sharing isn't applicable.

2. create n join nodes each rule which uses 2 or more object patterns. in other words: if (object1 (blah...) ) (object2 (blah) ) then ....

3. create n input nodes for each unique ObjectType

4. create a terminal node immediately after the last join, or after the last alpha node if the rule has no joins.

5. you should also see an index created at the nodes that matched a fact. this means both alpha and beta node.

6. at runtime, you should see the object first enter the network at the corresponding ObjectType node. if it doesn't, then it most definitely isn't RETE.

thank you for taking time to challenge my claims. the information you provided is helpful, but it creates more questions.

peter

  Message #183342 Post reply Post reply Post reply Go to top Go to top Go to top

from Forgy's paper

Posted by: peter lin on September 01, 2005 in response to Message #182318
Here is a paragraph from Forgy's 1985 paper, which may shed some light.
1.2. Work on production system efficiency
Since execution speed has always been a major issue for production systems. several researchers have worked on the problem of efficiency. The most common approach has been to combine a process called indexing with direct interpretation of the LHSs. In the simplest form of indexing, the interpreter begins the match process by extracting one or more features from each working memory element, and uses those features to hash into the collection of productions. This produces a set of productions that might have satisfied LHSs.
The interpreter examines each LHS in this set individually to determine whether it is in fact satisfied. A more efficient form of indexing adds memory to the process. A typical scheme involves storing a count with each pattern. The counts are all zero when execution of the system begins. When an element enters working memory, the indexing function is executed with the new element as its only input, and all the patterns that are reached have their counts increased by one. When an element leaves working memory, the index is again executed, and the patterns that are reached have their counts decreased by one. The interpreter performs the direct interpretation step only on those LHSs that have non-zero counts for all their patterns. Interpreters using this scheme—in some cases combined with other efficiency measures—have been described by McCracken [8], McDermott, Newell, and Moore [9), and Rychener [10].

a few sentence after the above paragraph, Forgy states:
The Rete algorithm was first described in 1974 [3]. A 1977 paper (4] described some rather complex interpreters for the networks of feature recognizers, including parallel interpreters and interpreters which delayed evaluation of patterns as long as possible. (Delaying evaluation is useful because it makes it less likely that patterns will be evaluated unnecessarily.) A 1979 paper [5] discussed simple but very fast interpreters for the networks. This article is based in large part on the
1979 paper.

Forgy then goes on to state clearly:
The box receives information about the changes that are made to working memory, and it determines the changes that must be made in the conflict set to keep it consistent. For example, the black box might be told that the element
   (Goal T Type Simplify T Object Exprl9)
has been added to working memory, and it might respond that production TimexN has just become instantiated.

the copy I have has a typo "conflict set is a keep it consistent". I took the liberty of correcting it. Obviously, people experiment with RETE and try to optimize it. I've done quite a bit of work on optimizing RETE and finding novel ways of improving rule compilation and runtime efficiency. Most of the ideas I've explored have been tried by other people and they generally produce results that do not scale like RETE.

The point I'm trying to make is this. In the process of exploring and experimenting with RETE, it's very easy to do the wrong thing and make it non-RETE. I try to be paranoid about it and verify my results thoroughly. Any time a person starts to modify RETE, most of the time it ends up being not RETE. Performance and scalability both take a hit. RETE has been proven in hundreds of papers and thousands of real-world systems. When the rules are written declaratively, the performance of RETE is factor of the network size, not the number of rules.

Or put it another way. If someone buys a F40 kit and puts it on a Pinto, it might look like an expensive Italian race car, but it can't reach 200mph, nor can it do 0-60 in the same amount of time. Looking at the public API gives no indication biztalk's rule engine implements RETE. Biztalk rule engine API.

Can anyone see the internal API in a profiler to confirm it has alpha node, beta node, join node, terminal node, input node, and indexes?

peter lin

  Message #183353 Post reply Post reply Post reply Go to top Go to top Go to top

Clarification

Posted by: peter lin on September 01, 2005 in response to Message #183309
The real issue here is that there is an impedance between the OO model represented by .NET objects and the head/slot model typically used in Rete-based engines.
I treid searching Forgy's 1985 paper for the terms "head/slot","head", and "slot" and wasn't able to find any references. I am not familiar with that terminology and Forgy's paper doesn't use that terminology. Could clarify what you mean by "head/slot". I also searched other RETE related papers and didn't find that terminology. In the RETE rule engine world, there are two types of facts:

ordered - a sequence of facts
unordered - deftemplate is equivalent to an object

CLIPS has a language called COOL (clips object oriented language). Many rule engines have been using OO concepts since the early 80's when ART came out with their RETE engine. I don't consider OO-ness an issue, since rules should be written in a declarative format. OO maps very easily to declarative programming, so I consider that a none issue.
Microsoft allows developers to exploit the rich OO model directly within their rules without any particular restriction, but this means that they map 'slots' not only to accessor methods, but also to other methods including voids and static members.

The real danger of this approach is abuse. An expert user can utilize these techniques, but a novice will most likley use it incorrectly. One of the biggest issues for the rule engine world is the steep learning curve. It doesn't really matter who it is, the learning curve is very steep. It takes several years of working deep in a rule engine to really understand the subtleties.

I'm hoping you'll respond, since I find the discussion interesting. Here is a bit more from Forgy's paper:
As explained above, the black box must maintain state information because it must know what is in working memory. In simple Rete networks all such state is stored by the two-input nodes. Each two-input node contains two lists called It’s left and right memories. The left memory holds copies of the tokens that arrived at its left input, and the right memory holds copies of the tokens that arrived at its right input. The tokens are stored as long as they are useful. The next section explains how the nodes determine when the tokens are no longer useful.

Forgy's explanation of join (ie two-input) nodes is pretty clear. In the case of clips for example, the left input is beta memory and the right is the alpha memory. There are some variation on this, but this form is the optimal implementation.
Both kinds of one-input nodes could be represented as single words that are divided into three fields. The first field would hold the type of the node. The second field would hold the index of the value to test. The third field would
hold either a constant or a second index. The bits in a word could be allocated as follows A sixteen-bit field is required to represent an integer or an atom using the
format of Section 3.1. Since a floating point number cannot be represented in sixteen bits, in nodes that test floating point numbers, this field would hold not the number, but the address of the number.

In the quote above, Forgy explains one possible implementation of alpha (1-input) nodes. The implementation I donated to Drools follows Forgy's original RETE pretty closely. The algorithm is not at all obvious, but it is quite simple. Many people skip the alpha memory for edge cases and get better performance. In fact TREAT algorithm does exactly that.

http://citeseer.csail.mit.edu/hanson92rule.html
http://drools.org/Publications

With my limited knowledge, one would have to "mis-implement" RETE to not achieve RETE scalability. Just because something looks like RETE, the final proof is in the scalability.

peter

  Message #183356 Post reply Post reply Post reply Go to top Go to top Go to top

Yes I am.

Posted by: Charles Young on September 01, 2005 in response to Message #183335
My view on the side effects issue is that Microsoft has implemented a straight-forward trade-off for practical purposes. When using XML documents and datasets, the engine works in a classic fashion, creating shadows, caching the data and thereby preventing data from being changed in working memory by another process. When using .NET objects, the cache is switched off by default. I agree that this can reasonably be characterised as 'impure', but I think that it is quite wrong to state that the engine is therefore not Rete-based. I just don't get it. Rete is an algorithm for maximising matching performance by using node sharing and state retention (alpha and beta memory). Truth maintenance is an important aspect in any deductive system, but surely the fact that Microsoft has given us some limited control over this does not in any way change or invalidate the core matching algorithm. My view is that this 'impurity' is entirely reasonable and practical. I entirely understand that you may disagree with that statement, but I find the claim that the engine in not therefore Rete-based to be extreme! Given your stance on this, would you then accept that, if side-effects are switched off for .NET objects (which is easily done), the engine magically becomes Rete-based? How exactly does the side effects feature change the matching algorithm?

I knew my head/slot statement would cause trouble, which is why I adopted the slightly strange terminology of describing WorkingMemoryElement as being 'at the centre of' this model. WorkingMemoryElement is simply what the name suggests (as per fairly common terminology in text-book descriptions of Rete). I was trying to stress the fact that the engine really does have a genuine working memory, and that the physical representation of facts is abstracted using much the same conceptual model employed in other Rete-based engines. This remains the case when using .Net objects, and hence, although I accept that the default 'side effects' feature is 'impure', it does not, as you suggested, mean that the engine has no genuine working memory.

Driving home this evening, I started thinking more deeply about Microsoft's performance figures, and it occurred to me that we may both be missing the blindingly obvious. If you look again at the whitepaper, you will see that Microsoft provides an illustration of the type of rule they implemented, as follows:

If ( ClassN.Attribute >= constant )
Then {Do something}

The example rule will surely result in the Rete containing condition nodes only, and no join nodes. If there are no join nodes, there is no use of beta memory. I think we would both agree that the performance characteristics of Rete are primarily influenced by partial match retention in beta memory. However, it looks like the simple rules used in the test only result in the use of alpha memory, and I also suspect that Microsoft’s test ruleset did not really get any noticeable benefit from node sharing. I would expect that for such simple rules, the performance of Rete would be linearly dependant on the number of rules - exactly what the graphs show! The trouble here is that the BizTalk team appear to have implemented their test using rules that are so extremely simple, they really don't benefit, in terms of performance, from being represented as a Rete. The test therefore surely proves nothing about the use, or otherwise, of the Rete algorithm. Put another way, I can't see that a given implementation of the Rete algorithm would ever guarantee a particular ruleset-size/activations-per-second ratio. The performance of the Rete will depend on the benefit gained principally from partial match retention (beta nodes), secondarily from minimisation of condition/constant filtering (alpha nodes), and thirdly from node sharing. This, in turn, is driven by the complexity of the rules in the ruleset. Lots of simple rules get little benefit. Lots of complex rules get a lot.

As I said in my earlier post, the BizTalk team were not responsible for implementing the rules engine, and the people who did the performance tests probably did not have enough knowledge to understand that their tests are actually failing to show the true performance benefits of the Rete approach when using large rulesets with at least a degree of complexity within those rules.

I am considering publishing the Miss Manners implementation at some point, but will need to jump through some commercial hoops first. In the meantime, I would prefer to decline saying which engine I tested against. I have a healthy suspicion of all benchmarking figures, including my own, and especially of comparative benchmarking. I just don't want to get into the position of appearing to claim that one engine is faster than another based on some quick and dirty tests done, as I recall, on a virtual PC image running on a memory-starved notebook!! There are other issues as well. Miss Manners is, in my opinion, not a good benchmark for comparative tests (Waltz is, I suspect, better, but I haven't got round to implementing this yet). For example, it is, I think, too highly sensitive to the exact behaviour of the conflict resolver. I also remain unimpressed by the argument that Miss Manners shows how the engine behaves when stressed. Yes, it does stress the engine, but only by the artificial device of adopting a really inefficient approach to solving the seating problem. You would never implement a real-life solution in this fashion, so can we really say it is a trustworthy guide to the likely performance in live systems. Another (minor) issue is that the original implementation assumes that you can perform existence checks on working memory ('if fact x does not exist...'). Many engines, including Microsoft's, do not support this, although Microsoft does implement an XPath-based 'exists' predicate for use with XML-based facts only. And also, as we all know, a lot of vendors have 'cheated' in their implementations of Miss Manners, so you never really quite know what you are comparing!

I have only implemented Miss Manners using .NET object facts. I always intended to create three implementations for the three different fact representation types. Perhaps I should do this and then publish (if I am allowed) the code and results (obtained on a 'proper' platform!!).

  Message #183363 Post reply Post reply Post reply Go to top Go to top Go to top

Good points

Posted by: peter lin on September 02, 2005 in response to Message #183356
My view on the side effects issue is that Microsoft has implemented a straight-forward trade-off for practical purposes. When using XML documents and datasets, the engine works in a classic fashion, creating shadows, caching the data and thereby preventing data from being changed in working memory by another process. When using .NET objects, the cache is switched off by default. I agree that this can reasonably be characterised as 'impure', but I think that it is quite wrong to state that the engine is therefore not Rete-based. I just don't get it. Rete is an algorithm for maximising matching performance by using node sharing and state retention (alpha and beta memory). Truth maintenance is an important aspect in any deductive system, but surely the fact that Microsoft has given us some limited control over this does not in any way change or invalidate the core matching algorithm. My view is that this 'impurity' is entirely reasonable and practical. I entirely understand that you may disagree with that statement, but I find the claim that the engine in not therefore Rete-based to be extreme!
I totally agree that my position is extreme. I am trolling for a response from microsoft. So I apologize for the extreme stance. I was hoping someone from microsoft who is technical would point out the position is extreme. I'm more than happy to apologize to Microsoft once more concrete proof is provided to the public.
Given your stance on this, would you then accept that, if side-effects are switched off for .NET objects (which is easily done), the engine magically becomes Rete-based? How exactly does the side effects feature change the matching algorithm? I knew my head/slot statement would cause trouble, which is why I adopted the slightly strange terminology of describing WorkingMemoryElement as being 'at the centre of' this model. WorkingMemoryElement is simply what the name suggests (as per fairly common terminology in text-book descriptions of Rete).
I haven't read any text books on RETE to be blunt, since I don't have a CS degree of any sort. My experience is primarily from reading Forgy's original papers and looking at CLIPS.
I was trying to stress the fact that the engine really does have a genuine working memory, and that the physical representation of facts is abstracted using much the same conceptual model employed in other Rete-based engines. This remains the case when using .Net objects, and hence, although I accept that the default 'side effects' feature is 'impure', it does not, as you suggested, mean that the engine has no genuine working memory.
You're right that the "impure" feature doesn't necessarily mean the rule engine isn't RETE. On the otherhand, having working on rule engines, my definition a RETE working memory is very specific. It is explicitly what Dr. Forgy defined in his papers. There may be other "interpretations" of RETE and there are tons of them. Of the papers on RETE I've read, I do not like most of them, since they gloss over critical details for the sake of making the topic more accessible to students.
Driving home this evening, I started thinking more deeply about Microsoft's performance figures, and it occurred to me that we may both be missing the blindingly obvious. If you look again at the whitepaper, you will see that Microsoft provides an illustration of the type of rule they implemented, as follows:

If ( ClassN.Attribute >= constant ) Then {Do something}

The example rule will surely result in the Rete containing condition nodes only, and no join nodes. If there are no join nodes, there is no use of beta memory. I think we would both agree that the performance characteristics of Rete are primarily influenced by partial match retention in beta memory.
Actually, that is one of the biggest misunderstanding of RETE. The primary benefit of storing an alpha memory is when a fact is "retracted" from the working memory. If the alpha nodes do not store an index for each fact, doing a retract would require traversing all alpha (1-input) nodes. The other main benefit of alpha memory is that when new nodes are added to the network, the rule engine only has to evaluate from the alpha nodes that already matched. Say for example at alphnode2 there's 4 matches, if I add a new alphanode to alphanode2, it only has to propogate the 4 matches to the new node. In rule engines that do not implement alpha memory, it would have to evaluate all alpha nodes.

The benefit of beta memory and alpha memory at the join (2-input) nodes is that for each new fact, the engine only needs to match facts which entered the node. All facts that did not reach that specific beta node do not need to be evaluated. This is one reason why Manners benchmark is a good measure of pattern matching performance. It really operates most efficiently when both alpha and beta memory are implemented. Rule engines that do not will generally see exponential increase as the number of guests increases.
However, it looks like the simple rules used in the test only result in the use of alpha memory, and I also suspect that Microsoft’s test ruleset did not really get any noticeable benefit from node sharing. I would expect that for such simple rules, the performance of Rete would be linearly dependant on the number of rules - exactly what the graphs show!
The tests I ran in JESS did not have any shared conditions, therefore the scalability factor exhibited by JESS is a good measurement of how RETE scales. One major factor in the scalability of RETE is how many alpha node a given input (aka objecttype) node has. That basically means that if there's 5K rules, but each input node only has 100 alpha nodes, the performance is the same as 200 rules with the same ratio of objectype node to alpha node. The performance document didn't list all the rules, since that isn't practical. It would be good to see exactly what rules Microsoft used for the benchmark. Even in the simple case, the performance is rarely linearly dependent on the number of rules. For the sake of exploration. If I write a rule which uses a Path for the key and the node for the value, I have to iterate over all the keys and figure out if I should assert the fact to that node. In this case, I would see linear dependency on the number of rules.
The trouble here is that the BizTalk team appear to have implemented their test using rules that are so extremely simple, they really don't benefit, in terms of performance, from being represented as a Rete.
This is also another common misunderstanding of RETE. The primary benefit of the compilation part of RETE is that facts enter the input (objecttype) node, which reduces the number of conditions the rule engine has to match against. The other benefit is the runtime improvement through indexing.
The test therefore surely proves nothing about the use, or otherwise, of the Rete algorithm. Put another way, I can't see that a given implementation of the Rete algorithm would ever guarantee a particular ruleset-size/activations-per-second ratio. The performance of the Rete will depend on the benefit gained principally from partial match retention (beta nodes), secondarily from minimisation of condition/constant filtering (alpha nodes), and thirdly from node sharing. This, in turn, is driven by the complexity of the rules in the ruleset. Lots of simple rules get little benefit. Lots of complex rules get a lot.
from first hand experience building pre-trade compliance for financial systems, that's not what I see. Even for simple rules, the benefit of RETE is atleast 100x faster than procedural rule engines. About the only way to get faster evaluation of simple rules would be to not store alpha memory like TREAT algorithm.
As I said in my earlier post, the BizTalk team were not responsible for implementing the rules engine, and the people who did the performance tests probably did not have enough knowledge to understand that their tests are actually failing to show the true performance benefits of the Rete approach when using large rulesets with at least a degree of complexity within those rules. I am considering publishing the Miss Manners implementation at some point, but will need to jump through some commercial hoops first. In the meantime, I would prefer to decline saying which engine I tested against. I have a healthy suspicion of all benchmarking figures, including my own, and especially of comparative benchmarking. I just don't want to get into the position of appearing to claim that one engine is faster than another based on some quick and dirty tests done, as I recall, on a virtual PC image running on a memory-starved notebook!! There are other issues as well. Miss Manners is, in my opinion, not a good benchmark for comparative tests (Waltz is, I suspect, better, but I haven't got round to implementing this yet). For example, it is, I think, too highly sensitive to the exact behaviour of the conflict resolver.
conflict resolution only affects the performance depending on the RETE topology. In other words, rules with long sequence of simple conditions benefit from a depth first conflict strategy, whereas rules with lots of different objects and a few simple conditions benefit from breadth strategy. For the two domains I've worked on: wireless and compliance, depth first is usually the most optimal. This is because there's a few (less than 500) distinct objects and and average of 3-10 simple conditions and 2-3 joins.
I also remain unimpressed by the argument that Miss Manners shows how the engine behaves when stressed. Yes, it does stress the engine, but only by the artificial device of adopting a really inefficient approach to solving the seating problem. You would never implement a real-life solution in this fashion, so can we really say it is a trustworthy guide to the likely performance in live systems.
this is just my opinion, but the purpose of manners is to measure pattern matching and indexing performance. it purposely forces combinatorial pattern matching to stress the rule engine. You're right that real world applications try to avoid combinatorial matching. It's generally bad to do that and there should be a strong case for it. I generally rewrite rules to avoid combinatorial matching. Manners is a great benchmark for measuring pattern matching and index performance, but that in no way tells you how a "real" application performs. Those with several years of experience know that and accept manners results for what it is.
Another (minor) issue is that the original implementation assumes that you can perform existence checks on working memory ('if fact x does not exist...'). Many engines, including Microsoft's, do not support this, although Microsoft does implement an XPath-based 'exists' predicate for use with XML-based facts only. And also, as we all know, a lot of vendors have 'cheated' in their implementations of Miss Manners, so you never really quite know what you are comparing!I have only implemented Miss Manners using .NET object facts.
You're right that many vendors try to cheat by changing the algorithm of the benchmarks, but usually people find out and call them on it. I know of one case where a company did that and was called on it. Often, people cheat by making the hobbies a list of the guest, rather than asserting multiple guests with different hobbies. The other cheat is to explicitly short circuit the evaluation. It's easy enough to google for it and find it.
I always intended to create three implementations for the three different fact representation types. Perhaps I should do this and then publish (if I am allowed) the code and results (obtained on a 'proper' platform!!).

I look forward to your results. My methods may appear overzelous or extreme, but I'm an equal opportunity offender. I've called out several companies in the past when they try to claim RETE doesn't scale or that their "proprietary" algorithm is faster than RETE. My motivation is getting the facts out on RETE and debunking false claims. There are plenty of companies that love to claim RETE is bad, so my concern is that others will use microsoft's results to back their own claims. I think it's more appropriate to call a product "RETE derivative" or "inspired by RETE" when the implementation strays from Forgy's algorithm. There already enough confusion about what "RETE is" that I think it's huge disservice to call something it isn't. But I accept that it's part of what marketing guys do, even if the developers cringe and recommend the opposite. If no one makes a fuss, marketing guys will continue to abuse terminology. Not that my trolling will make any difference or result in any action by microsoft's excellent marketing team.

peter

  Message #183468 Post reply Post reply Post reply Go to top Go to top Go to top

corrections to my post

Posted by: peter lin on September 02, 2005 in response to Message #183363
If the alpha nodes do not store an index for each fact, doing a retract would require traversing all alpha (1-input) nodes.

my own fault for not proof reading. That should have been all alpha nodes for the object type. Alpha nodes for all other object types in the RETE network do not need to be traversed in the case a rule engine does not store alpha memory and a fact is retracted. Storing the alpha memory greatly reduces the number of alpha nodes (of a given object type) the rule engine needs to retract a given fact.

peter

  Message #183525 Post reply Post reply Post reply Go to top Go to top Go to top

What I think happened...and other matters

Posted by: Charles Young on September 04, 2005 in response to Message #183363
think the performance issue can only be satisfactorily progressed by undertaking some intelligent testing of the engine. I can't promise to do this anytime very soon, but I will see what I can put together.

In the meantime, I strongly suspect that Microsoft's performance test was so simplistic that it effectively circumvented all the optimisations of Rete. Lets review what we are told, and make a few assumptions. The rules are very basic, consisting of a single condition that tests against a constant, and an action list that probably does not perform any asserts or retracts. Hence, it is likely that the Rete contained no beta nodes, and that no forward chaining occurred. Indeed, the Rete would have consisted of a rather 'flat' structure of alpha nodes taking input from the input nodes (Microsoft calls these 'class' nodes) and outputting directly to terminal nodes. We are told that "different .NET classes were used for the rules in the policy", which indicates that Microsoft probably asserted a number of facts of different types. I suspect (it is a guess on my behalf) that they created a certain number of almost identical classes, created a number of instances of these classes and asserted them as facts, and had rules which simply tested some value on each fact.

Given that the test involved the use of rulesets containing between 1,000 and 10,000 rules, Microsoft must have generated their rules either in-memory using the API or by generating XML. Let’s speculate that they had five different fact types, and hence five input nodes. We will further assume that they created their rules to test fact types in a round-robin fashion (i.e., rule 1 tests type A, rule 2 tests type B, etc., with rule n1 going back to testing type A and starting a round 'round'). For the 1,000 rule test they would end up with 200 alpha nodes per input node. Let’s say they asserted 5 instances of each fact type. There would have to be 5 * 200 (1,000) alpha traversals. Now, if Microsoft then generated a 2,000-rule ruleset using the same round-robin approach, and using unique constants in their conditions, each of the five input nodes would now have 400 alpha nodes. Assert the same 25 facts, and there would now be 2,000 alpha traversals, taking approximately twice as long. With no beta nodes, and no forward chaining, the test as a whole would take approximately twice as long to complete, and you would get exactly the kind of graph Microsoft shows.

I realise this speculation and guesswork proves nothing about the implementation of the Microsoft Rules Engine. However, it does suggest that a perfectly reasonable explanation can be given, based on the partial information provided, which would lead to the results. There is no need to assume that the engine is not using Rete. Rather, we might speculate that some BizTalk guys, who did not have a good understanding of the Rete algorithm, came up with a very simple test that they thought showed a really nice classic linear scale, without realising that in fact they are showing the engine behaving at its least efficient!

You'll be amused to know that I spent time this weekend writing a test for Drools using rulesets of the sort I suspect Microsoft used in their test (as described above), and got an identical result to Microsoft's (2x linear scale). However, I am not particularly familiar with Drools, and am uncertain about its status re. Rete. The web site appears to claim to be implemented on Rete (Rete-OO), but I understand, from what you have said elsewhere, that this is not correct, and that you have written an implementation of the algorithm (or at least the alpha memory part of the algorithm) which the Drools team are currently integrating into their engine in order to make it truly Rete-compliant. If this is the case, I guess my Drools test proves nothing, unless, perhaps, Drools is currently capable of performing Rete-like node sharing. Do please let me know the current status. Is there a beta version of Drools available with a true Rete implementation?

We might ask if there is any evidence in the Microsoft performance paper that actively supports the claim that the engine is using Rete? Well, yes there is actually. I think maybe you would not have picked up on this, as not having experience of this particular engine, you may not have realised the implications of one of the tests. On pages 72 and 73, Microsoft reports the result of a test under the title “Increasing the Number of Conditions”. This is one of a series of tests investigating performance in relation to the use of facts asserted as ADO.NET datasets where a connection to the underlying data source is exploited. Microsoft explains the test as follows:

"This test used a policy that contained 100 rules, and changed the number of unique conditions in the rules.

Rule N

If (Table1.Column1 = (N Mod NumberofUniqueConditions)
Then Class1.Property1 = Table1.Column1

The purpose of the test was to show how the data connection binding becomes much more efficient when the rule set uses shared conditions/queries."

The resulting graph shows a very significant increase in performance as the number of ‘unique queries’ contained in the conditions of the rules is reduced to 1. If the engine is using Rete, then with NumberofUniqueConditions set to 1, there would be just one alpha node for the condition of Table1.Column1 = 0. While I accept that this does not prove a correct implementation of Rete, it is, nevertheless, clear evidence that the engine is behaving in a Rete-like fashion. The performance characteristic is exactly what would be expected as a result of alpha node sharing. In fact, I have looked pretty hard at the code, and can confirm that this is exactly what would happen in this case.

Implementation Details

I can help with the details of how the engine is implemented. While it is true that I don't have access to the source code, Microsoft has not obfuscated their compiled code, and there are some good reflection tools out there for .NET. I hope Microsoft won't mind me providing a high-level description of their implementation and the names of some of their internal classes. My point is that, as you will see, the Microsoft developers clearly believed they were implementing Rete.

Microsoft implements their Rete engine in a namespace (similar to a Java package) called Microsoft.RuleEngine.Rete. The 'executor' is represented by a top-level class called Rete. The executor is initialised by a translator class called RuleSetToReteTranslator which creates the Rete directly from a given ruleset. Note that Executors and Translators are just two of several different pluggable components within the Microsoft Business Rules Framework, and the classes I am describing are the implementation provided 'out of the box' by Microsoft.

Microsoft represents different Rete node types using node classes. Here is a class diagram showing the inheritance hierarchy (sorry, it will probably need copying and pasting in a fixed-pitch font to view correctly).

                                        +-------------+
                                        | NetworkNode |
                                        +-------------+
                                               ^
                                              / \
                                             /___\
                                               |
                                               |
            +------------------+---------------+----------------+
            | | | |
            | | | |
      +----------+ +----------------+ +-------------+ +--------------+
      | RootNode | | ClassNode | | MemoryNode | | TerminalNode |
      +----------+ +----------------+ +-------------+ +--------------+
                                               ^
                                              / \
                                             /___\
                                               |
                                               |
                                     +---------+--------+
                                     | |
                                     | |
                            +-----------------+ +---------------+
                            | SelectNode | | JoinNode |
                            +-----------------+ +---------------+

The ClassNode class defines what, elsewhere, might be called input or type nodes. The SelectNode class defines alpha nodes and the JoinNode class defines beta nodes. Note how both these classes are derived from MemoryNode.

The full implementation of alpha and beta memory would take a fair amount of describing, but at its core, Microsoft implements alpha memory using an internal class called 'AlphaMemory'. This maintains a sorted (and partitioned) list of HashTables (HashMaps, in Java-speak). Each HashTable acts as a bucket of tokens, each containing a working memory element represented by the WorkingMemoryElement class. The sorted list is indexed on the 'literals' within a given condition. So, to summarise, alpha memory is a sorted list, sorted by 'literal' value, of buckets of WMEs. Conditions are represented using instances of a class called 'RelationalTest'. These contain the left and right arguments and a relational operator. Join classes (beta, 2-input nodes) have left- and right-memories. Each memory contains either a 1-input or a 2-input node. As I say, the implementation of alpha and beta memory is fairly involved (I haven’t unravelled it totally), but suffice to say that you get your indexing at both alpha and beta nodes.

The agenda is represented by a class called 'PrioritizedAgenda' which is derived from an abstract class called 'Agenda'. PrioritizedAgenda maintains an internal queue (implemented in a class called PriorityQueue) of instances of a class called 'Production'. Production instances represent rules, and maintain a list of actions represented by Action and derived Argument objects. Productions are queued in priority order (the only conflict resolution strategy supported by the engine is a salience approach driven by a rule priority setting). Items are added to the agenda by terminal nodes.

As I say, I think it is fairly clear from the above that it certainly looks and smells like a Rete implementation when you look at the code.
 
Not the ‘BizTalk’ Rules Engine

Just one other small matter. You, naturally enough, have on several occasions referred to the Microsoft Business Rules Engine as the ‘BizTalk’ rules engine. It is true that at the current time, the only way of obtaining the engine is with a copy of BizTalk. This is a licensing thing, only, and we can be fairly certain that this will change over time as Microsoft releases new products and product versions to market. The engine is, as I began to describe above, a pluggable component (one of several) within an overall Business Rules Framework. As well as ‘executors’ and ‘translators’, Microsoft supports an entire framework for managing the capture and storage of rules and semantics. They supply a SQL Server repository and associated ‘Rules Composer’ tool, but the framework also comes with pre-built support for any OLE-DB rule repositories and also XML files. There is also an entire rule publishing framework (centred on a Windows service) that is decoupled from both rules stores and rule executors. If the truth be told, some of the tools are a little basic at present, but no doubt this will improve, and the framework is wide open to third-party plug-in, repository and tool development or integration with existing engines and frameworks. I mention this for information and clarity about the nature of the product, and also to draw a clear distinction between BizTalk, which is an enterprise level message routing and business process orchestration tool, and the rules engine. BizTalk is quite separate to, and not in any way dependant on the rules engine, although there is some very lightweight integration with the framework in order to allow rules and rules engines to be exploited within automated business processes.

  Message #183529 Post reply Post reply Post reply Go to top Go to top Go to top

What I think happened...and other matters

Posted by: peter lin on September 04, 2005 in response to Message #183525
First thing, thanks for spending your own time to explore microsoft's rule engine and writing a detailed response. I'm thankful of your response.
Hence, it is likely that the Rete contained no beta nodes, and that no forward chaining occurred. Indeed, the Rete would have consisted of a rather 'flat' structure of alpha nodes taking input from the input nodes (Microsoft calls these 'class' nodes) and outputting directly to terminal nodes. We are told that "different .NET classes were used for the rules in the policy", which indicates that Microsoft probably asserted a number of facts of different types. I suspect (it is a guess on my behalf) that they created a certain number of almost identical classes, created a number of instances of these classes and asserted them as facts, and had rules which simply tested some value on each fact.
That was my guess also. If microsoft were to publish the rules used for to benchmark would really help clarify things. The rules I generated for JESS looked like this.

(defrule rule0 (fact nsh00) => (printout t "rule0 was fired" crlf))
......
(defrule rule1000 (fact nsh0999) => (printout t "rule0 was fired"

I tried 2 different methods of execution. The first was to call "(run") after a single fact is asserted. The second was to assert all facts and then execute "(run"). The result of my simple test was:
721ms - run after each assert
671 - run after all facts are asserted

I also generate 5K, 10, 15K rules and ran the benchmark. 15K rules took 89649ms, which is about 6ms per rule. That means for this specific case, rulset size increased 15x, but performance decreased 6x.
Given that the test involved the use of rulesets containing between 1,000 and 10,000 rules, Microsoft must have generated their rules either in-memory using the API or by generating XML. Let's speculate that they had five different fact types, and hence five input nodes. We will further assume that they created their rules to test fact types in a round-robin fashion (i.e., rule 1 tests type A, rule 2 tests type B, etc., with rule n1 going back to testing type A and starting a round 'round'). For the 1,000 rule test they would end up with 200 alpha nodes per input node. Let’s say they asserted 5 instances of each fact type. There would have to be 5 * 200 (1,000) alpha traversals. Now, if Microsoft then generated a 2,000-rule ruleset using the same round-robin approach, and using unique constants in their conditions, each of the five input nodes would now have 400 alpha nodes. Assert the same 25 facts, and there would now be 2,000 alpha traversals, taking approximately twice as long. With no beta nodes, and no forward chaining, the test as a whole would take approximately twice as long to complete, and you would get exactly the kind of graph Microsoft shows.
That is a plausible explanation for the performance. In my simple test using deffacts, JESS generates a RETE network which branches out from 1 node to the "nsh####" nodes. That means there was 1K, 5K, 10K, 15K nodes branching out from 1 node. You can see a sample in this screen capture of just 4 rules <img src="http://cvs.apache.org/~woolfel/simple_network.png">. The network I generated with the simples rules were actually far worse than the case you described. With each assert, the rule engine has to traverse all "nsh##" alpha nodes.
I realise this speculation and guesswork proves nothing about the implementation of the Microsoft Rules Engine. However, it does suggest that a perfectly reasonable explanation can be given, based on the partial information provided, which would lead to the results. There is no need to assume that the engine is not using Rete. Rather, we might speculate that some BizTalk guys, who did not have a good understanding of the Rete algorithm, came up with a very simple test that they thought showed a really nice classic linear scale, without realising that in fact they are showing the engine behaving at its least efficient!

You'll be amused to know that I spent time this weekend writing a test for Drools using rulesets of the sort I suspect Microsoft used in their test (as described above), and got an identical result to Microsoft's (2x linear scale). However, I am not particularly familiar with Drools, and am uncertain about its status re. Rete.
I may be able to shed some light on the current Drools release. The current implement does not implement alpha memory and uses arbitrary joins. It took me several months of discussions with the developers to figure exactly what the current implementation does. The reason Drools shows exactly the same scalability is that it isn't RETE. That's one reason why the documentation now makes that distinction and states it is only forward chaining. The other thing Drools currently does is it use global bindings for objects, which doesn't follow RETE. In a strict RETE implementation, variable bindings are local to a rule. This greatly reduces the lookup time for objects and improves performance. Using global bindings does not produce the scalability of RETE. So one might conclude that microsoft's rule engine is very similar to the current RETE implementation and in fact is not RETE.
The web site appears to claim to be implemented on Rete (Rete-OO), but I understand, from what you have said elsewhere, that this is not correct, and that you have written an implementation of the algorithm (or at least the alpha memory part of the algorithm) which the Drools team are currently integrating into their engine in order to make it truly Rete-compliant. If this is the case, I guess my Drools test proves nothing, unless, perhaps, Drools is currently capable of performing Rete-like node sharing.
Drools currently doesn't really implement node sharing, but it is being worked on. One of the areas that I am exploring is aggressive node sharing through node re-ordering and rule optimization. Re-ordering alpha nodes is simpler to implement. In theory, it's feasible to re-order the joins, but I haven't quite worked out the algorithm for doing that in a generic and reliable way that doesn't "corrupt" or change the intent of the rule.
Do please let me know the current status. Is there a beta version of Drools available with a true Rete implementation? We might ask if there is any evidence in the Microsoft performance paper that actively supports the claim that the engine is using Rete? Well, yes there is actually. I think maybe you would not have picked up on this, as not having experience of this particular engine, you may not have realised the implications of one of the tests. On pages 72 and 73, Microsoft reports the result of a test under the title “Increasing the Number of Conditions”. This is one of a series of tests investigating performance in relation to the use of facts asserted as ADO.NET datasets where a connection to the underlying data source is exploited. Microsoft explains the test as follows:

"This test used a policy that contained 100 rules, and changed the number of unique conditions in the rules. Rule N

If (Table1.Column1 = (N Mod NumberofUniqueConditions) Then Class1.Property1 = Table1.Column1

The purpose of the test was to show how the data connection binding becomes much more efficient when the rule set uses shared conditions/queries."
This proves it absolutely is a "forward chaining" rule engine. Even a simple forward chaining rule engine that implements node sharing will show this type of performance. it's not necessary to implement strict RETE to see this kind of scalability and performance.
The resulting graph shows a very significant increase in performance as the number of ‘unique queries’ contained in the conditions of the rules is reduced to 1. If the engine is using Rete, then with NumberofUniqueConditions set to 1, there would be just one alpha node for the condition of Table1.Column1 = 0. While I accept that this does not prove a correct implementation of Rete, it is, nevertheless, clear evidence that the engine is behaving in a Rete-like fashion.
It's matter of preference, but I don't believe in "RETE-like". A rule engine either implements RETE, or it's just a "forward chaining" rule engine. That is one of the primary differences between various "forward chaining" implementations and RETE.
The performance characteristic is exactly what would be expected as a result of alpha node sharing. In fact, I have looked pretty hard at the code, and can confirm that this is exactly what would happen in this case.

Implementation Details

I can help with the details of how the engine is implemented. While it is true that I don't have access to the source code, Microsoft has not obfuscated their compiled code, and there are some good reflection tools out there for .NET. I hope Microsoft won't mind me providing a high-level description of their implementation and the names of some of their internal classes. My point is that, as you will see, the Microsoft developers clearly believed they were implementing Rete.Microsoft implements their Rete engine in a namespace (similar to a Java package) called Microsoft.RuleEngine.Rete. The 'executor' is represented by a top-level class called Rete. The executor is initialised by a translator class called RuleSetToReteTranslator which creates the Rete directly from a given ruleset. Note that Executors and Translators are just two of several different pluggable components within the Microsoft Business Rules Framework, and the classes I am describing are the implementation provided 'out of the box' by Microsoft.

Microsoft represents different Rete node types using node classes. Here is a class diagram showing the inheritance hierarchy (sorry, it will probably need copying and pasting in a fixed-pitch font to view correctly).

The ClassNode class defines what, elsewhere, might be called input or type nodes. The SelectNode class defines alpha nodes and the JoinNode class defines beta nodes. Note how both these classes are derived from MemoryNode.
I didn't know that, so thanks for the information. That does strongly suggest Microsoft's rule engine implements some form of alpha and beta memory. Having said that, having memory doesn't necessarily mean the implementation is RETE. I've seen some implementations that index, but they index the wrong thing and end up being "not RETE".
The full implementation of alpha and beta memory would take a fair amount of describing, but at its core, Microsoft implements alpha memory using an internal class called 'AlphaMemory'. This maintains a sorted (and partitioned) list of HashTables (HashMaps, in Java-speak). Each HashTable acts as a bucket of tokens, each containing a working memory element represented by the WorkingMemoryElement class. The sorted list is indexed on the 'literals' within a given condition. So, to summarise, alpha memory is a sorted list, sorted by 'literal' value, of buckets of WMEs.
For comparison, CLIPS uses a linkedlist for both alpha and beta memories, which makes sense for C. If your description of the memory is accurate, that could very well be the cause of the poor performance. Of the implementation I know of, the index uses a hash of the fact, and not the literal value. Without seeing the actual code, it's hard to know if Microsoft implemented the indexing incorrectly.
Conditions are represented using instances of a class called 'RelationalTest'. These contain the left and right arguments and a relational operator. Join classes (beta, 2-input nodes) have left- and right-memories. Each memory contains either a 1-input or a 2-input node. As I say, the implementation of alpha and beta memory is fairly involved (I haven't unravelled it totally), but suffice to say that you get your indexing at both alpha and beta nodes.

The agenda is represented by a class called 'PrioritizedAgenda' which is derived from an abstract class called 'Agenda'. PrioritizedAgenda maintains an internal queue (implemented in a class called PriorityQueue) of instances of a class called 'Production'. Production instances represent rules, and maintain a list of actions represented by Action and derived Argument objects. Productions are queued in priority order (the only conflict resolution strategy supported by the engine is a salience approach driven by a rule priority setting). Items are added to the agenda by terminal nodes.
Most everyone gets the terminal part right, since that's probably the easiest part of implementing RETE.
As I say, I think it is fairly clear from the above that it certainly looks and smells like a Rete implementation when you look at the code. &nbsp;Not the ‘BizTalk’ Rules EngineJust one other small matter. You, naturally enough, have on several occasions referred to the Microsoft Business Rules Engine as the ‘BizTalk’ rules engine. It is true that at the current time, the only way of obtaining the engine is with a copy of BizTalk. This is a licensing thing, only, and we can be fairly certain that this will change over time as Microsoft releases new products and product versions to market.
my only response to that is, that I'm ignorant to what the official name of the rule engine is. for that I apologize for creating any confusion, since the rule engine is currently packaged with Biztalk and isn't sold as stand alone.
The engine is, as I began to describe above, a pluggable component (one of several) within an overall Business Rules Framework. As well as ‘executors’ and ‘translators’, Microsoft supports an entire framework for managing the capture and storage of rules and semantics. They supply a SQL Server repository and associated ‘Rules Composer’ tool, but the framework also comes with pre-built support for any OLE-DB rule repositories and also XML files. There is also an entire rule publishing framework (centred on a Windows service) that is decoupled from both rules stores and rule executors. If the truth be told, some of the tools are a little basic at present, but no doubt this will improve, and the framework is wide open to third-party plug-in, repository and tool development or integration with existing engines and frameworks. I mention this for information and clarity about the nature of the product, and also to draw a clear distinction between BizTalk, which is an enterprise level message routing and business process orchestration tool, and the rules engine. BizTalk is quite separate to, and not in any way dependant on the rules engine, although there is some very lightweight integration with the framework in order to allow rules and rules engines to be exploited within automated business processes.

Thanks again for taking time to provide more information and spending time to explain what you see. The details you provided show solid proof the rule engine is forward chaining and implements some form of node sharing. Whether it meets all the requirements of RETE is still uncertain, but hopefully this discussion helps others make a more informed decision. The most interesting result is that Drools shows the same scalability for the simple benchmark described in microsoft's biztalk document.

peter

  Message #183530 Post reply Post reply Post reply Go to top Go to top Go to top

link to screen capture

Posted by: peter lin on September 04, 2005 in response to Message #183529
doh, I forgot TSS strips out the link.

http://people.apache.org/~woolfel/simple_network.png

peter

  Message #183570 Post reply Post reply Post reply Go to top Go to top Go to top

An interesting paper...

Posted by: Charles Young on September 05, 2005 in response to Message #183530
I happened across an interesting paper at http://reports-archive.adm.cs.cmu.edu/anon/usr/ftp/home/ftp/1992/CMU-CS-92-158.ps. The paper has some relevance to this discussion. It looks at the 'clash of views' on how alpha and beta match time tends to increase as rulesets are increased. Essentially, it contrasts the worlds of parallel production systems and EBL (Explanation Based Learning).

The Microsoft test results provide an example of what the authors call 'Average Growth Effect', or AGE. For parallel production systems, the expectation, we are told, is that adding large numbers of rules leads to little or no AGE. In EBL systems, the expectation, apparently, is exactly the opposite, and the paper even has an 'AGE Prediction' graph looking just like the Microsoft results.

The authors of the paper analysed this conflict of expectations using test production systems implemented using SOAR, and they specifically state that they used the Rete algorithm. They implemented three very different production systems. Two of them exhibited little or no AGE, and the third exhibited some AGE (a 2x slowdown for each 6-fold increase in the rules).

They conclude that "the presence or absence of AGE appears related to particular tasks (or domains) and encoding styles". They state that "...an acknowledgement that the existing match algorithms (the specifically appear to have Rete in mind here) cannot alleviate the AGE...could be considered as a key outcome of our investigation".

Please note that I mention this as a point of interest only, and not as some kind of counter argument to anything you have said. Your position, I believe, is that rules engines built on the Rete algorithm can and often do exhibit a degree of AGE (I love discovering new acronyms!), but not, as a general observation, to the degree that the Microsoft figures exhibit. I totally agree with this, although I think we may have a reasonable explanation for the MS figures.

  Message #183576 Post reply Post reply Post reply Go to top Go to top Go to top

An interesting paper...

Posted by: peter lin on September 05, 2005 in response to Message #183570
I happened across an interesting paper at http://reports-archive.adm.cs.cmu.edu/anon/usr/ftp/home/ftp/1992/CMU-CS-92-158.ps. The paper has some relevance to this discussion. It looks at the 'clash of views' on how alpha and beta match time tends to increase as rulesets are increased. Essentially, it contrasts the worlds of parallel production systems and EBL (Explanation Based Learning).

The Microsoft test results provide an example of what the authors call 'Average Growth Effect', or AGE. For parallel production systems, the expectation, we are told, is that adding large numbers of rules leads to little or no AGE. In EBL systems, the expectation, apparently, is exactly the opposite, and the paper even has an 'AGE Prediction' graph looking just like the Microsoft results.

The authors of the paper analysed this conflict of expectations using test production systems implemented using SOAR, and they specifically state that they used the Rete algorithm. They implemented three very different production systems. Two of them exhibited little or no AGE, and the third exhibited some AGE (a 2x slowdown for each 6-fold increase in the rules).

They conclude that "the presence or absence of AGE appears related to particular tasks (or domains) and encoding styles". They state that "...an acknowledgement that the existing match algorithms (the specifically appear to have Rete in mind here) cannot alleviate the AGE...could be considered as a key outcome of our investigation".

Please note that I mention this as a point of interest only, and not as some kind of counter argument to anything you have said. Your position, I believe, is that rules engines built on the Rete algorithm can and often do exhibit a degree of AGE (I love discovering new acronyms!), but not, as a general observation, to the degree that the Microsoft figures exhibit. I totally agree with this, although I think we may have a reasonable explanation for the MS figures.

I agree the paper is interesting, but that doesn't apply to this specific case. I know of several cases where RETE would exhibit 2x slow down, but those cases are primarily in agent systems that attempt to "learn" and acquire new knowledge. What that means in practice is the pattern matching is typically combinatorial, or overly eager. When a rule is written such that a large number of partial matches are produced, a strict RETE implementation will show a dramatic decrease in performance.

To put it in perspective, the same thing done with procedural rule engines or simple forward chaining rule engines that do not index would see an exponential increase in match time. As good as RETE is, there are some problems that are computationally intensive and require combinatorial matching. In those cases, the performance can and will degrade rapidly. Some algorithms like RETE-UL attempt to address this class of problems by un-linking RETE nodes. In an agent system that produces new deftemplates, facts and rules at runtime, the RETE network can become inefficient. RETE-UL attempts to identify nodes that are not used and un-links them. That reduces the cost of matching and reduces the likelihood of "useless" nodes from clogging the rule engine.

I'm not an expert and there plenty of aspects of RETE which I am still exploring. For the simple case of rules with 1 condition, the match time should not increase by "n" as the number of rules increases by "n". I've only read about 30 or so papers on RETE, so there's plenty I don't know. I know a few individuals who know this domain far better than I do and they were also puzzled by the results for the simple rules.

I know of a few other rule engines that also claim RETE, but don't really implement it.

I agree there may be a reasonable explanation for the performance figures. It's rather unlikely for the simple rules used in the benchmark, but I agree there is a slight chance. The only people who can prove this beyond a doubt is Microsoft, but so far they've decided not to respond. Ragardless of microsoft, I have seen this type of performance from engines that do not implement RETE. I've been lucky enough to stumble across these issues and made the same mistake first hand. Frankly, there's no shame in making mistakes. I make mistakes every day.

My challenge to microsoft is to explain the results reported in their paper. If the rules used for the benchmark were more complex, I could understand a 2x decrease in performance as ruleset increases 2x in size. For the rules used in the paper, the evidence strongly suggests Microsoft mis-implemented RETE (ie, it's not RETE). It's up to each person to decide for themselves, since Microsoft hasn't taken the initiative to have a third party validate their implementation.

thanks again for taking time to respond.

peter

  Message #183696 Post reply Post reply Post reply Go to top Go to top Go to top

Looks like global bindings

Posted by: peter lin on September 06, 2005 in response to Message #182318
I took a look at some of the API in the ruleengine namespace. I've never seen the code, but looking at the API defined, it looks like microsoft's rule engine implements global bindings, which means the implementation is not the classic "slot based" implementation.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sdk/htm/frlrfmicrosoftruleengineclassbindingmemberstopic.asp

if it was slot based, the API would have methods for retrieving the value of a given slot. One way to implement it would be row + column. The documentation suggests the rule engine does not use the classic slot based approach and prefers to use Object Oriented techniques. That kind of design decision could easily result in someone mis-implementing RETE.

peter

  Message #184119 Post reply Post reply Post reply Go to top Go to top Go to top

more food for thought

Posted by: peter lin on September 11, 2005 in response to Message #182318
I spent some more time looking at MS business rule engine and it doesn't look like any RETE implementation. For example, both CLIPS and JESS define nodes such that a node has successors. If one looks at Microsoft's API, the classes do not contain such concepts. From what I can tell from the public API documentation, there's an Assert class. The documentation says "Represents the rule engine assert facts function."

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sdk/htm/frlrfmicrosoftruleenginetermmemberstopic.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sdk/htm/frlrfmicrosoftruleengineassertmemberstopic.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sdk/htm/frlrfmicrosoftruleenginetermmemberstopic.asp

Assert extends a class called Term, which we are told "Represents a term used in building rule conditions and actions." The telling part is that Term doesn't define an method for asserting methods or for getting a list of successor nodes. Does anyone know the correct class that really represents a RETE 1-input node? I'm unable to verify the class structure explained by Charles young. When I look at the API for the binding class, it definitely is not slot based implementation.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sdk/htm/frlrfmicrosoftruleenginebindingmethodstopic.asp

An implementation that takes a classic slot approach would need to know the slot, which could be a C# member or property. Instead the class defines Class type and variable name. In my own implementation of RETE, I chose to go with a minimal design, which defines:
variable name
left column id
left row id
right column id
right row id

Any implementation that doesn't do that is implementing global variable bindings, which definitely does not produce RETE scalability. It's a common mistake. The other thing the API reveals is that Microsoft's BRE does not generate sequential joins and probably goes with an arbitrary join approach. That's another common mistake and also results in poor scalability. It's really quite a shame the .NET community is being told BRE is RETE, when the API strongly suggests it isn't. Without implementing these concepts at the bind, and node level, BRE can't operate like a strict RETE engine.

peter lin

  Message #184712 Post reply Post reply Post reply Go to top Go to top Go to top

Its a rule 'term', not an engine function

Posted by: Charles Young on September 15, 2005 in response to Message #184119
Peter. Thanks for this, but you are quite mistaken. You cannot use the documented API to tell anything about the implementation of the Rete algorithm within the Microsoft Rules Engine for the simple reason that the Rete classes are undocumented. Unfortunately, this is not an open source product, and Microsoft doesn’t tell you everything about their code.

It is quite understandable that someone unacquainted with the Microsoft Business Rules Framework would assume that the Assert class implements a core function within the engine. However, this is not true, and completely misunderstands the purpose of this class and its relationship to the framework. The clue to the truth is contained within what you write. Assert is derived from Term, and this is its function.

The Microsoft Business Rules Framework is an entire framework for managing business rules, and provides the environment for many different types of pluggable component. These include Rule Language Converter components which convert a specific rule language into a normalised (please excuse my Brit spelling :-) ) object graph representing a ruleset. These graphs are then handed off to RuleSet Translator components whose task is to convert the rulesets into some executable format targeted to a specific 'Executor' component. Out of the box, Microsoft provides implementations of these components. The BusinessRulesLanguageConverter class is a Rule Language Converter that converts Microsoft's proprietary rule language (MS-BRL) into a RuleSet object graph. The RuleSetToReteTranslator class implements a RuleSet translator that generates a Rete from a RuleSet object graph. The RulesEngine class implements an Executor that executes Retes created by RuleSetToReteTranslator.

This architecture means that within the one common framework it is possible to convert and translate almost any rule language into any executable format, and to execute the rules via any engine (Rete, or otherwise). However, despite this flexibility, it should be noted that some of the classes provided by the framework were clearly designed with MS-BRL in mind. This includes the Assert class which, like other Term classes, is used by the BusinessRuleLanguageConverter to represent instructions within MS-BRL. Instances of Assert are contained within the object graph handed off to the RuleSet translator.

As you can see, the Assert class has nothing to do with the implementation of any specific rules engine, but, nevertheless, was doubtless created with the Microsoft RulesEngine executor in mind. It could, of course, be used as appropriate to represent Asserts which are actioned by other engines. Instances of the class Assert simply correspond to an 'Assert' action specified within a ruleset (in essence, they are de-serialised MS-BRL XML nodes). The RuleSetToReteTranslator sees these, and outputs Terminal nodes that contain Assert actions.

I hope Microsoft will excuse me including a couple of snippets of their code generated using a reflection tool. This code is contained within the BusinessRulesLanguageConverter class.
 

From a private method called ProcessBody…

    if (vrdr.Name == "assert")
    {
      actions.Add(this.ProcessAssert(vrdr, termCache, bindings));
      continue;
    }

(Note that vrdr is an instance of Microsoft's XmlValidatingReader class - a forward-only XML validating parser (a bit like SAX, only 'pull', not 'push'). It is being used to read an element within MS-BRL XML.)

The private ProcessAssert method, called in the above snippet, contains the following line:

    Assert assert1 = new Assert(term1);

 I hope this clears up any confusion.

  Message #184722 Post reply Post reply Post reply Go to top Go to top Go to top

Jess, Drools and MS-BRE comparison

Posted by: Charles Young on September 16, 2005 in response to Message #183529
As a first step to addressing this issue by looking at performance characteristics, I have published a paper reporting a series of tests undertaken using Jess, Drools and the Microsoft BRE. These figures do do prove a correct implementation of Rete, but do show that Jess, which, I believe, is accepted as providing a correct implementation of the Rete algorithm, displays exactly the same scaling characteristics as both the other engines when used to execute a test similar to that described in Microsoft's performance whitepaper. I have included full details, and the source code used, so the tests can be run and verified by anyone who is interested. I have some formatting issues, so for the next couple of days you will find the code in appendicies b and c is difficult to read. I'll fix this soon.

The paper is at:

http://geekswithblogs.net/cyoung/articles/54022.aspx

If you don't want to read the whole paper, here are the important graphs. The first shows the results published by Microsoft. The second shows my results. The important feature is the linear scale factor (time doubles when ruleset size doubles). As I explain in the aticle I have doctored the y-axis of my result to allow easier comparison. The actual times are shown in appendix e.


http://geekswithblogs.net/images/geekswithblogs_net/cyoung/507/o_brecomp01.gif
http://geekswithblogs.net/images/geekswithblogs_net/cyoung/507/o_brecomp02.gif

  Message #184738 Post reply Post reply Post reply Go to top Go to top Go to top

Typo alert...

Posted by: Charles Young on September 16, 2005 in response to Message #184722
Sorry...meant to say "These figures do *not* prove a correct implementation of Rete..."

  Message #185221 Post reply Post reply Post reply Go to top Go to top Go to top

Further results

Posted by: Charles Young on September 20, 2005 in response to Message #184738
For those following the debate on the implementation of the Rete algorithm in the Microsoft Business Rules Engine, you may be aware that I undertook to port some CLIPS/Jess tests provided by Peter Lin to the MS-BRE and to publish the results. This follows on from the original article I published here:

http://geekswithblogs.net/cyoung/articles/54022.aspx

My results for the ported tests are documented here.

http://geekswithblogs.net/cyoung/articles/54476.aspx

They show virtually identical scaling behaviour between Jess and the MS-BRE.

  Message #185328 Post reply Post reply Post reply Go to top Go to top Go to top

thanks to Mr Young

Posted by: peter lin on September 21, 2005 in response to Message #185221
thanks to Charles young for taking time to run the tests. I think Microsoft should pay him for his time. the best evidence is the mixed ruleset test, which correctly shows constant time performance. Though even for the case of 1 object and thousands of rules, the performance doesn't have to be linear. It can easily be constant if hashing is used to further narrow which branches should be evaluated.

peter

 
New content on TheServerSide.NETNew content on TheServerSide.NETNew content on TheServerSide.NET

DSLs and language interop

Language "mashups" will become more prominent, and developers will become polyglots, one programmer suggests.

VS 2008 Resources

SearchWinDevelopment.com offers an introduction to the language, performance, testing and data management improvements in VS 2008.

VB code downloads home

VBCode.com code snippets cover all aspects of application development, from data binding to security to the user interface.

XAML Learning Guide

Get up to date on XAML best practices with a variety of articles, tutorials and webcasts. [SearchWinDevelopment.com]

Company uses VSTS DB edition to tame workflow

One team's experience with the VSTS DB edition suggests that it can improve workflow for dev teams. It also enhanced Agile efforts. (June 24, Article)

Book: Intro to DSL Tools

Microsoft has begun to include DSL tools in the VSTS kit. A new book by Steve Cook and other VSTS team members helps set the stage. (June 24, Article)

I See the Silverlight Shining!

Cartoon: Be it ever so humble there is no place like your home after you get a Microsoft Home Server . (June 18, Cartoon)

A look at .NET 3.5

Microsoft's Thom Robbins says new technology to highlight in NET 3.5 includes AJAX, LINQ for both C# and VB, as well as tooling enhancements intended to ease the task of building WPF, WF and WCF apps. (June 29, Podcast)

Venkat Subramaniam on AJAX

Venkat Subramaniam discusses AJAX bottlenecks, the tenets of Agile development and more. He spoke at the Ajax Experience. (June 25, Tech Talk)

Building a Claims-Based Security Model in WCF - Part 2

In the second of a two-part series, Michele Leroux Bustamente discusses design decisions related to the claims-based security model. Read the story and walk through the process for creating a set of claims-based utilities to encapsulate claims authorization at the service tier. (May 24, Article)

Introducing the Entity Framework

Understanding why the Entity Framework exists and learning where it can fit into your projects can get you prepared for the eventual release early next year. (May 10, Article)

WCF Security Learning Guide

Resource: This learning guide gives you quick access to useful links on Windows Communication Foundation security information. (April 24, Article)

Brad Abrams: Patterns for successful ASP.NET AJAX development

TSS.NET's Jack Vaughan spoke recently spoke with Microsoft's Brad Abrams to find out what he is seeing in the field and what the chefs in Redmond are cooking. Along the way he discusses patterns of AJAX frameworks. (April 11, Article)

Building a Claims-Based Security Model in WCF

In a two-part series, Michele Leroux Bustamente explains how claims-based security is supported by WCF, and how you can implement a claims-based security model for your services. (March 29, Article)

Authoring workflow using XAML

Windows Workflow Foundation is a new technology that many developers will need to get their heads around. In a brief excerpt adapted from Programming Windows Workflow Foundation: Practical WF Techniques and Examples using XAML and C#, K.Scott Allen considers aspects of workflow definition. (March 22, Chapter Excerpt)

News | Blogs | Discussions | Tech talks | Patterns | Reviews | White Papers | Downloads | Articles | Media kit | About
All Content Copyright ©2007 TheServerSide Privacy Policy
Site Map