Improving Drools Memory Performance
by Jevon Wright
Hi everyone,
I am working on what appears to be a fairly complex rule base based on
EMF. The rules aren't operating over a huge number of facts (less than
10,000 EObjects) and there aren't too many rules (less than 300), but
I am having a problem with running out of Java heap space (set at ~400
MB).
Through investigation, I came to the conclusion that this is due to
the design of the rules, rather than the number of facts. The engine
uses less memory inserting many facts that use simple rules, compared
with inserting few facts that use many rules.
Can anybody suggest some tips for reducing heap memory usage in
Drools? I don't have a time constraint, only a heap/memory constraint.
A sample rule in my project looks like this:
rule "Create QueryParameter for target container of DetailWire"
when
container : Frame( )
schema : DomainSchema ( )
domainSource : DomainSource ( )
instance : DomainIterator( )
selectEdge : SelectEdge ( eval (
functions.connectsSelect(selectEdge, instance, domainSource )) )
schemaEdge : SchemaEdge ( eval (
functions.connectsSchema(schemaEdge, domainSource, schema )) )
source : VisibleThing ( eContainer == container )
target : Frame ( )
instanceSet : SetWire ( eval(functions.connectsSet(instanceSet,
instance, source )) )
detail : DetailWire ( )
eval ( functions.connectsDetail(detail, source, target ))
pk : DomainAttribute ( eContainer == schema, primaryKey == true )
not ( queryPk : QueryParameter ( eContainer == target, name == pk.name ) )
eval ( handler.veto( detail ))
then
QueryParameter qp = handler.generatedQueryParameter(detail, target);
handler.setName(qp, pk.getName());
queue.add(qp, drools); // wraps insert(...)
end
I try to order the select statements in an order that will reduce the
size of the cross-product (in theory), but I also try and keep the
rules fairly human readable. I try to avoid comparison operators like
< and >. Analysing a heap dump shows that most of the memory is being
used in StatefulSession.nodeMemories > PrimitiveLongMap.
I am using a StatefulSession; if I understand correctly, I can't use a
StatelessSession with sequential mode since I am inserting facts as
part of the rules. If I also understand correctly, I'd like the Rete
graph to be tall, rather than wide.
Some ideas I have thought of include the following:
1. Creating a separate intermediary meta-model to split up the sizes
of the rules. e.g. instead of (if A and B and C then insert D), using
(if A and B then insert E; if E and C then insert D).
2. Moving eval() statements directly into the Type(...) selectors.
3. Removing eval() statements. Would this allow for better indexing by
the Rete algorithm?
4. Reducing the height, or the width, of the class hierarchy of the
facts. e.g. Removing interfaces or abstract classes to reduce the
possible matches. Would this make a difference?
5. Conversely, increasing the height, or the width, of the class
hierarchy. e.g. Adding interfaces or abstract classes to reduce field
accessors.
6. Instead of using EObject.eContainer, creating an explicit
containment property in all of my EObjects.
7. Creating a DSL that is human-readable, but allows for the
automation of some of these approaches.
8. Moving all rules into one rule file, or splitting up rules into
smaller files.
Is there kind of profiler for Drools that will let me see the size (or
the memory usage) of particular rules, or of the memory used after
inference? Ideally I'd use this to profile any changes.
Thanks for any thoughts or tips! :-)
Jevon
14 years, 5 months
Working with BRL format
by wilsonywx
I've been trying to make a custom GUI to edit rules and store them in a
format that is easily exchangeable between the GUI and the rule engine. It
seems that the BRL format (which from what I understand is just an xml
representation of the rules that belong in a package) is a good file format
to use (although I am not too clear on how the .package file works with the
.brl files). In the meanwhile I've been looking at the source code of
Guvnor, in hope that I could find some classes that can convert between brl
and drl, as well as between the class model of rules and brl.
I found snippets of code that uses BRXMLPersistence to read from brl (I
think) into a RuleModel object, which is then converted into a DRL string
using BRDRLPersistence, something like:
RuleModel model =
BRXMLPersistence.getInstance().unmarshal(asset.getContent()); // how to get
asset?
model.name = asset.getName();
model.parentName = this.parentNameFromCategory(asset, model.parentName);
String drl = BRDRLPersistence.getInstance().marshal(model); // is this the
entire rule text?
I am not sure how to interface RuleModel with the GUI, though, so I would
like some pointer in that direction. Also, what is the class to read from a
.package file so that I can generate a drl file with the correct package
attribute and imports?
--
View this message in context: http://drools-java-rules-engine.46999.n3.nabble.com/Working-with-BRL-form...
Sent from the Drools - User mailing list archive at Nabble.com.
14 years, 5 months
Rules not firing when expected after retracting object in list
by Justin Beltran
Hi,
I'm coming across some weird behavior in Drools 4.0.7, but maybe it's just
cause I don't understand I how Drools works. Assume, there's a class "A"
that has a property called "property".
As facts, I have the following list of A's:
A1, property = 123
A2, property = 345
A3, property = 123
I have two rules as follows:
rule "Rule 1 - Remove all A's that have property set to 123"
salience 1000
lock-on-active true
when
$listOfAs : ArrayList collect(A( property == "123" ))
then
for (Object a: $listOfAs ) {
retract (a)
}
end
rule "Rule 2 - Do stuff with remaining A's"
salience 900
lock-on-active true
when
$listOfAs : ArrayList collect(A())
then
...
end
My understanding is "Rule 1" will remove the facts of class A that have
property to 123. When it gets to "Rule 2", shouldn't the "listOfAs" only
have that one A that remains (i.e. the one where property is set to "345").
What I'm noticing is that "Rule 2" just doesn't execute at all even though
I'm assuming there is still one "A" object that hasn't been retracted. If I
comment out the "retract" it executes "Rule 2" fine.
Am I missing something about these rules work?
Thanks.
Justin
14 years, 5 months
collection question
by javaj
I'm trying to write a rule to add an object to a collection if the collection
already contained a certain object with a specific attribute.
I developed a small example so maybe that will make more sense:
Use Case: In a product shipping applicaiton, anytime a product with the name
"cd1" is in the shipping order, a bonus product named "bonus_cd" needs to be
added to the shipping order. The bonus cd should not be added if it's
already in the shipping order.
Shipping Order:
public class ShippingOrder {
private Set<Product> products;
public ShippingOrder() {}
public Set<Product> getProducts() {
return products;
}
public void setProducts(Set<Product> products) {
this.products = products;
}
}
Product:
public class Product {
private String name;
public Product(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Rule:
rule "AddBonusCd"
when
$so : ShippingOrder()
$productList : ArrayList(size == 1) from collect( Product(name matches
"cd1|bonus_cd") from $so.products)
then
System.out.println("Adding Bonus Cd");
Set<Product> productSet = new HashSet<Product>($so.getProducts());
Product bonusCd = new Product();
bonusCd.setName("bonus_cd");
productSet.add(bonusCd);
modify($so) {
setProducts(productSet);
}
end
The Shipping Order object is inserted as the fact.
The rule is valid if only cd1 or cd_bonus is in the shipping order. I only
want the rule to run when cd1 is in the product set but cd_bonus is not.
Makes sense?
Thanks,
J
--
View this message in context: http://drools-java-rules-engine.46999.n3.nabble.com/collection-question-t...
Sent from the Drools - User mailing list archive at Nabble.com.
14 years, 5 months
Drools Flow 5.1 - latest snapshot -- Gateway (Diverge) : Split Node - Priority Does not Work
by Vijay K Pandey
Hi All,
In the Drools Flow 5.1 latest snapshot , for the node (Gateway (Diverge) : Split Node), somehow priority does not work. If we set some value, lets say 100 and open the process file(BPMN2) again and check the priority - somehow it doesn't retains the priority value and reports the value always as 0.
I am trying to make use one of the feature of XOR type node where one of the constraint is "always true" with the highest priority. I hope my understanding is right.
This is what the Drools Flow Doc says:
XOR means that exactly one of the outgoing connections will be chosen. The decision is made by evaluating the constraints that are linked to each of the outgoing connections. Constraints are specified using the same syntax as the left-hand side of a rule. The constraint with the lowest priority number that evaluates to true is selected. Note that you should always make sure that at least one of the outgoing connections will evaluate to true at runtime (the ruleflow will throw an exception at runtime if it cannot find at least one outgoing connection). For example, you could use a connection which is always true (default) with a high priority number to specify what should happen if none of the other connections can be taken.
Has anyone faced this issue?
Thanks
Vijay
14 years, 5 months
Drools Flow - Human Task
by jawa
Hi,
I am developing a drools flow application and at one point of the flow I
want end user (User of my website) to reply to some questions one by one
i.e. I'll show them a question on a web page and they'll answer it then next
question etc. It has a flow sequence depending on the answers of questions.
e.g. If user replied 'No' to Q1 then go to Q5 else go to Q2 etc. So I want
my flow to stop for a user input when the flow reaches to the 'Ask question'
stage. I have read the drools flow documentation and it looks like there is
an option to use Human Task which will cause my flow to stop at that point
and wait for user input but for that I'll have to use Apache Mina server and
will need to claim tasks etc. But I don't want that because my front end
application is in php and backend (Drools flow) is in java and I connect
both using webservice. So I just want to ask my front end that ask question
then front end will reply with an answer that I want to feed to my flow then
flow will continue and decide which question to ask next. The website users
are anonymous it can be anyone answering the questions.
Can anyone please give me an idea how to achieve this using drools flow?
Thank you
--
View this message in context: http://drools-java-rules-engine.46999.n3.nabble.com/Drools-Flow-Human-Tas...
Sent from the Drools - User mailing list archive at Nabble.com.
14 years, 5 months
Implementing Timers With Drools Persistence Enabled
by nanic23
Hi All,
I was able to implement some timers and they behave as expected until I
enable persistence. Timers work (get triggered) when creating the
StatefulKnowledgeSession by kbase.newStatefulKnowledgeSession() but they do
NOT work (do not get triggered) when creating the StatefulKnowledgeSession
by JPAKnowledgeService.newStatefulKnowledgeSession(kbase, null, env);
I am calling ksession.fireUntilHalt() from within a new thread and all that.
The problem is not getting timers to work, as I have already accomplished
this, but the problem is rather getting them to work with persistence
enabled.
- Has anyone implemented timers while using (having enabled) persistence?
- Did you experience any problems such as timers not triggering?
- If so, have you found a work around you could share?
The timers are being implemented in ruleflow (DRF) and I'm using drools
5.1.0
Any comments are welcome.
Thanks,
Nick.
--
View this message in context: http://drools-java-rules-engine.46999.n3.nabble.com/Implementing-Timers-W...
Sent from the Drools - User mailing list archive at Nabble.com.
14 years, 5 months