Drools 4 poor performance scaling?
by Ron Kneusel
I am testing Drools 4 for our application and while sequential mode is very fast I get very poor scaling when I increase the number of facts for stateful or stateless sessions. I want to make sure I'm not doing something foolish before deciding on whether or not to use Drools because from what I am reading online it should be fast with the number of facts I have.
The scenario: I have 1000 rules in a DRL file. They are all of the form:
rule rule0000
when
Data(type == 0, value> 0.185264);
Data(type == 3, value < 0.198202);
then
insert(new AlarmRaised(0));
warnings.setAlarm(0, true);
end
where the ranges checked on the values and the types are randomly generated. Then, I create a Stateful session and run in a loop timing how long it takes the engine to fire all rules as the number of inserted facts increases:
// Run
for(j=0; j < 100; j+=5) {
if (j==0) {
nfacts = 1;
} else {
nfacts = j;
}
System.out.println(nfacts + ":");
// Get a working memory
StatefulSession wm = ruleBase.newStatefulSession();
// Global - output
warnings = new Alarm();
wm.setGlobal("warnings", warnings);
// Add facts
st = (new Date()).getTime();
for(i=0; i < nfacts; i++) {
wm.insert(new Data(rand.nextInt(4), rand.nextDouble()-0.5));
}
en = (new Date()).getTime();
System.out.println(" facts = " + (en-st));
// Now run the rules
st = (new Date()).getTime();
wm.fireAllRules();
en = (new Date()).getTime();
System.out.println(" rules = " + (en-st));
// Clean up
wm.dispose();
System.out.println("\n");
}
This code is based on the HelloWorldExample.java code from the manual and the setup for the rule base is the same as in the manual. As the number of facts increases runtime increases dramatically:
facts -- runtime (ms)
10 -- 168
20 -- 166
30 -- 344
40 -- 587
50 -- 1215
60 -- 1931
70 -- 2262
80 -- 3000
90 -- 4754
with a maximum memory use of about 428 MB RAM. By contrast, if I use sequential stateless sessions, everything runs in about 1-5 ms.
Is there something in my set up that would cause this, or is this how one would expect Drools to scale? I read about people using thousands of facts so I suspect I'm setting something up incorrectly.
Any help appreciated!
Ron
_________________________________________________________________
The other season of giving begins 6/24/08. Check out the i’m Talkathon.
http://www.imtalkathon.com?source=TXT_EML_WLH_SeasonOfGiving
16 years, 4 months
simple rule takes long time
by ygaurav
Hi All
I am new to drools and I am trying to see if we can use it. I have a simple
file
public class Data {
private int id =0;
public Data(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
rule "Unique data"
when
data : Data()
old : Data(this != data, this.id == data.id)
then
log.log("Following data are not unique: " + data.getId() + " and " +
old.getId());
end
When I try to load 30,000 of data in memory it takes long time ( around 12
hours ) Can anybody suggests a better way of doing it.
Thanks
Gaurav
--
View this message in context: http://www.nabble.com/simple-rule-takes-long-time-tp18192098p18192098.html
Sent from the drools - user mailing list archive at Nabble.com.
16 years, 5 months
Unexpected global error
by thomas kukofka
Hello,
I get this exception: Exception in thread "main" java.lang.RuntimeException:
Unexpected global [service]
That's the global declaration in the drl: global java.util.HashMap service
And ther I set teh global in teh Java-class:
HashMap<String, AIOObject> service = new HashMap<String, AIOObject>();
workingMemory.setGlobal("service", service);
Appreciate your help!
Kind Regards
Thomas
16 years, 5 months
Parsing input text file
by Amit Kumar
Hi All ,
I am new to this drools technology and want to do a prototype for
checking its feasibility for our use.
Most of the places I believe it will work fine.. but I have a use case
of parsing input files recd in different formats.
Scenario:
I have 2 input files
1.
##############################
Test config Start
100 bytes available 250 bytes total
1000 bytes is my life goal
##############################
2:
##############################
Test config Start
200 bytes available 300 bytes used 500 bytes total
2000 bytes is my life goal
##############################
I have to extract the numbers from here and populate an output
objects.. containing whatever value is possible.. so for the first
instance I will be able to populate 3 values.. but for the second one
I will be able to extract 4 values
I wrote a file to work on the first case but I am unable to get it working.
Can somebody help me to complete this prototype.. (I am very new to
this so please pardon my ignorance.. I just looked at help file and am
trying to build this :) )
Thanks for looking..
- Amit
###########################################################
ParsingExample.java
###########################################################
package org.drools.examples;
import java.io.InputStreamReader;
import org.drools.FactHandle;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.StatefulSession;
import org.drools.audit.WorkingMemoryFileLogger;
import org.drools.compiler.PackageBuilder;
import java.util.*;
public class ParsingExample {
/**
* @param args
*/
public static void main(final String[] args) throws Exception {
final PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader(
ParsingExample.class.getResourceAsStream( "Parsing.drl" ) ) );
final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage( builder.getPackage() );
final StatefulSession session = ruleBase.newStatefulSession();
final WorkingMemoryFileLogger logger = new WorkingMemoryFileLogger( session );
logger.setFileName( "log/OutputObj" );
String config = "";
config += "Test config Start\n";
config += " 100 bytes available 250 bytes total\n";
config += " 1000 bytes is my life goal";
String[] configA = config.split("\n");
List configL = new ArrayList();
for (int i=0; i < configA.length; i++) {
configL.add(new Row(configA ));
}
final Lines l1 = new Lines( configL );
final InputConfig a = new InputConfig( l1 );
final OutputObj t1 = new OutputObj();
session.insert( a );
session.insert( t1 );
config = "";
config += "Test config Start\n";
config += " 200 bytes available 300 bytes used 500 bytes total\n";
config += " 2000 bytes is my life goal";
configA = config.split("\n");
configL = new ArrayList();
for (int i=0; i < configA.length; i++) {
configL.add(new Row(configA ));
}
final Lines l2 = new Lines( configL );
final InputConfig b = new InputConfig( l2 );
final OutputObj t2 = new OutputObj();
session.insert( b );
session.insert( t2 );
session.fireAllRules();
session.dispose();
logger.writeToDisk();
}
public static class Row {
private String val;
public Row() {
}
public Row(final String val) {
this.val = val;
}
public String getVal() {
return this.val;
}
public String toString() {
return "[Row " + " : " + this.val + "]";
}
}
public static class Lines {
private List rows;
public Lines() {
}
public Lines(final List rows) {
this.rows = rows;
}
public List getRows() {
return this.rows;
}
public String toString() {
return "[Lines " + " : " + this.rows.toString() + "]";
}
}
public static class InputConfig {
private Lines config;
public InputConfig() {
}
public InputConfig(final Lines config) {
this.config = config;
}
public Lines getConfig() {
return this.config;
}
public String toString() {
return "[InputConfig " + " : " + this.config.toString() + "]";
}
}
public static class OutputObj {
private String bu = "";
private String ba = "";
private String bt = "";
private String blg = "";
public OutputObj() {
}
public String getBu() {
return this.bu;
}
public void setBu(final String bu) {
this.bu = bu;
}
public String getBa() {
return this.ba;
}
public void setBa(final String ba) {
this.ba = ba;
}
public String getBt() {
return this.bt;
}
public void setBt(final String bt) {
this.bt = bt;
}
public String getBlg() {
return this.blg;
}
public void setBlg(final String blg) {
this.blg = blg;
}
public String toString() {
return "[OutputObj " + " used: " + this.bu +" avail: " + this.ba + "
total: " + this.bt + " Goal: " + this.blg + "]";
}
}
}
###########################################################
Parsing.drl
###########################################################
package org.drools.examples
import org.drools.examples.ParsingExample.InputConfig;
import org.drools.examples.ParsingExample.OutputObj;
import org.drools.examples.ParsingExample.Lines;
import org.drools.examples.ParsingExample.Row;
rule "get Bytes v10"
salience 10
when
$o : OutputObj()
$i : InputConfig()
InputConfig( $conf : config)
$row : rows( val matches "^\\s*\\d+\s+bytes available\s+\d+\s+bytes
total\s*$") from $i.config
then
eval($o.bu = /$row/^\s*(\d+)\s+bytes available\s+\d+\s+bytes total\s*$/)
eval($o.bt = /$row/^\s*\d+\s+bytes available\s+(\d+)\s+bytes total\s*$/)
System.out.println("BU:" + $o.bu);
System.out.println("BT:" + $o.bt);
end
16 years, 5 months
Creating attributes of facts
by Amit Kumar
Hi,
I need to create properties/attributes of a fact. Like today I am
checking for Color of a box. Tomorrow I want to Check Width also of a
Box.
Can I make this change just in the rule and attach it to some object
and pass it forward through the rule chain? I do not want to add Width
Attribute to Box.. as I will have to recompile the java files also in
that case.
I do not see this scenario in the documentaion. Where can I find
better examples.
Thanks,
Amit
16 years, 5 months
xml parsing bug
by Paul Alexandrow
Hi list,
I've encountered some strange behaviour (bug?) in Drools (4.0.7) when
adding packages from XML. Take the following rule as an example:
<rule name="constraintTest">
<lhs>
<pattern identifier="$foo" object-type="Bar" >
<field-constraint field-name="a">
<literal-restriction evaluator="==" value="A" />
</field-constraint>
<or-constraint-connective>
<and-constraint-connective>
<field-constraint field-name="b">
<literal-restriction evaluator="==" value="B" />
</field-constraint>
<field-constraint field-name="c">
<literal-restriction evaluator="==" value="C" />
</field-constraint>
</and-constraint-connective>
<field-constraint field-name="d">
<literal-restriction evaluator="==" value="D" />
</field-constraint>
</or-constraint-connective>
</pattern>
</lhs>
<rhs>
log("constraintTest");
</rhs>
</rule>
Trying to add a package from this gives the following Error:
org.drools.compiler.DroolsParserException:
org.xml.sax.SAXParseException: <or-constraint-connective> is after an
invalid element: org.drools.xml.Handler
at
org.drools.compiler.PackageBuilder.addPackageFromXml(PackageBuilder.java:184)
Now here's what's strange: If you rewrite the pattern like this
<pattern identifier="$foo" object-type="Bar" >
<or-constraint-connective>
<and-constraint-connective>
<field-constraint field-name="b">
<literal-restriction evaluator="==" value="B" />
</field-constraint>
<field-constraint field-name="c">
<literal-restriction evaluator="==" value="C" />
</field-constraint>
</and-constraint-connective>
<field-constraint field-name="d">
<literal-restriction evaluator="==" value="D" />
</field-constraint>
</or-constraint-connective>
<field-constraint field-name="a">
<literal-restriction evaluator="==" value="A" />
</field-constraint>
</pattern>
in other words (and I tried this with a couple of variations), if you
put all field-constraints after any and-constraint-connectives or
or-constraint-connectives sharing the same parent element, the package
adds just fine.
I couldn't find any reason, why this should be intended behaviour, so I
assume it's a bug.
I took a little peek into Drools' source, and my guess is, that there's
just some 'validPeers' missing in one of the *Handler classes that are
responsible for the validation of Drools XML configuration files.
However, this really is just my first guess.
'Adds just fine' is not the whole truth though: Modifying the pattern as
described above, still leaves me with the following message (strangely
printed to stdout, instead of using a logger or throwing an exception):
(null: 33, 46): cvc-complex-type.2.4.a: Invalid content starting with
element 'field-constraint'. One of
'{"http://drools.org/drools-4.0":and-constraint-connective}' is expected.
Now, if I wrap the "d" field-constraint (see my example) into an
and-constraint-connective (and thus being the field-constraint the only
element in the and-constraint-connective, which looks rather useless),
that message goes away.
Even more oddness: the "a" field-constraint doesn't cause such a message
- even without a wrapping it into an and-constraint-connective.
Many thanks in advance,
Paul
16 years, 5 months
Globals in LHS
by thomas kukofka
Hello,
Is it possible to evaluate a global on the LHS of rule?
Like:
global SomeGlobal someGlobal
rule "xy"
when
someGlobal.getValue() <= 3
then
....
end
Kind Regards
Thomas
16 years, 5 months
QueryResult.getFactHandles bug?
by Fenderbosch, Eric
I didn't find a JIRA for this and I'm pretty sure my test is valid.
QueryResult.getFactHandles() seems to be only returning [fid:-1:X:null]
I'm using 4.0.7.
Here's my test case:
public void testQueryResults() throws Exception {
StatefulSession workingMemory = DroolsUtil.getWorkingMemory();
TestFact testFact = new TestFact();
String id = "1234";
testFact.setId(id);
FactHandle testHandle = workingMemory.insert(testFact);
System.out.println(testHandle);
Object[] args = {id};
int resultCount = 0;
int factCount = 0;
int handleCount = 0;
Object fact = null;
FactHandle handle = null;
// query getTestFact(String _id)
// TestFact(id == _id)
// end
QueryResults queryResults =
workingMemory.getQueryResults("getTestFact", args);
Iterator<QueryResult> iterator = queryResults.iterator();
while (iterator.hasNext()) {
resultCount++;
QueryResult result = iterator.next();
FactHandle[] handles = result.getFactHandles();
for (FactHandle h : handles) {
handleCount++;
handle = h;
}
for (int i = 0; i < result.size(); i++) {
factCount++;
fact = result.get(i);
}
}
System.out.println(handle);
assertTrue(resultCount == 1);
assertTrue(factCount == 1);
assertTrue(testFact == fact);
assertTrue(handleCount == 1);
// this fails
assertTrue(testHandle == handle);
}
TestFact is very simple, using id in hashCode and equals.
Am I using getFactHandles correctly?
Thanks.
16 years, 5 months