Edson Tirelli (JIRA) was heard to exclaim, On 04/11/07 05:57: > Edson Tirelli commented on JBRULES-740: > Being brief, using the following rule: > rule "Find all PRs for user" > when > $user : User( ) > $pr_list : RecordSet( size > 0 ) from > collect( PRRecord( $resp : responsible -> ( $user.hasReport($resp) ) ) ) > then > $user.setRecords($pr_list, DataSource.GNATS); > end > if you already have "User" facts asserted into the working memory, it means > that for every PRRecord that matches your <constraints>, it will recalculate > the "collect". So, if you have a User fact, and assert a PRRecord, it will > create a RecordSet and add your PRRecord to the set. When you assert a second > PRRecord, it will create a new RecordSet and add the 2 PRRecord. As you see, > it is a progression: 1+2+3+4...+N. Your case is even worst because your > constraint is a predicate (not indexable right now), so, it means the > progression above is executed in full.
As it turns out, this is actually quite fast; it takes 50-100 msec per PR assertion, so I can cram in 10,000 of them in a few minutes. Nonetheless, I understand that it is less than optimal at the moment. > Anyway, what you need to do: > 1) If possible, adjust your business model in a way to replace the predicate > for a regular "==" constraint, avoiding full iteration because of indexing. There's no way to do that. What I really want is this: $user : User( $reports : reports ) $pr_list : RecordSet( size > 0 ) from collect( PRRecord( $reports contains responsible ) ) (the syntax could also be "responsible containedIn $reports"). But Drools doesn't (yet?) support that. For now, I could warp my application such that I could write this: collect( PRRecord( responsible_users contains $user ) ) Is that something that Drools could index? That would introduce some unpleasant dependencies in my code, but if it allows indexing, it might be worth it. > 2) Use a control fact to limit the partial matches. Example: > rule "Find all PRs for user" > when > $control : ControlFact( phase == "findPR" ) > $user : User( ) > $pr_list : RecordSet( size > 0 ) from > collect( PRRecord( $resp : responsible -> ( $user.hasReport($resp) ) ) ) > then > $user.setRecords($pr_list, DataSource.GNATS); > $control.setPhase( "do everything else" ) > modify( $control ) > end > Doing the above, make sure you assert all PRRecords first and only then, set > (or assert) your control fact to phase "findPR". The above will make the > engine avoid wasting time calculating partial matches that will never be > used. It seems ugly at first, but it is a technique that unfortunately needs > to be used in some special cases. That doesn't really fit with the application flow. I could have a rule like this: when ControlFact( ) $user : User( ) $pr_list : RecordSet( size > 0 ) from collect( PRRecord( $resp : responsible -> ( $user.hasReport($resp) ) ) ) then $user.setRecords($pr_list, DataSource.GNATS); And retract the ControlFact before asserting PR objects, then assert it when I'm ready to fireAllRules(). Would that have the desired effect? Thanks. -- Dirk Bergstrom [EMAIL PROTECTED] _____________________________________________ Juniper Networks Inc., Computer Geek Tel: 408.745.3182 Fax: 408.745.8905 _______________________________________________ rules-users mailing list [EMAIL PROTECTED] https://lists.jboss.org/mailman/listinfo/rules-users
