I am trying to improve the performance of compiling our rules into packages.
I started to making the process into threads. The build server is multicore
so multi-threads should help.
However, I found it was slower in threads compared to a single compile..
So I did some digging.. (Drools 5.5.0)
Below is a sample java application I created.
What it does is create a StringBuilder with 30000 rules in it.
Then it compiles the rules.
Next, it creates 4 StringBuilders, putting 7500 rules in each, and compiles
each of them in a thread.
The results are:
Single Thread:
Starting build size=2508946
Time to compile:16963 ms
Multi Thread:
Thread [3] compile time=15455 ms
Thread [2] compile time=15580 ms
Thread [0] compile time=15633 ms
Thread [1] compile time=15674 ms
Time to compile:16075 ms
So, the single compile takes 16 seconds.. The 4 threads take 16 seconds..
If I watch the process, only 1 thread is running at a time, all the other
threads are blocked..
with the following:
Name: Thread-3
State: BLOCKED on sun.misc.Launcher$AppClassLoader@138d107f owned by:
Thread-1
Total blocked: 16,135 Total waited: 0
Stack trace:
java.lang.Class.forName0(Native Method)
java.lang.Class.forName(Class.java:249)
org.drools.util.CompositeClassLoader$CachingLoader.load(CompositeClassLoader.java:258)
org.drools.util.CompositeClassLoader$CachingLoader.load(CompositeClassLoader.java:237)
org.drools.util.CompositeClassLoader.loadClass(CompositeClassLoader.java:88)
java.lang.ClassLoader.loadClass(ClassLoader.java:247)
java.lang.Class.forName0(Native Method)
java.lang.Class.forName(Class.java:249)
org.mvel2.optimizers.AbstractOptimizer.forNameWithInner(AbstractOptimizer.java:166)
org.mvel2.optimizers.AbstractOptimizer.tryStaticAccess(AbstractOptimizer.java:79)
org.mvel2.compiler.PropertyVerifier.getBeanProperty(PropertyVerifier.java:257)
org.mvel2.compiler.PropertyVerifier.analyze(PropertyVerifier.java:117)
org.mvel2.compiler.ExpressionCompiler.verify(ExpressionCompiler.java:407)
org.mvel2.compiler.ExpressionCompiler._compile(ExpressionCompiler.java:273)
org.mvel2.compiler.ExpressionCompiler.compile(ExpressionCompiler.java:62)
org.mvel2.MVEL.analyze(MVEL.java:680)
org.mvel2.MVEL.analyze(MVEL.java:685)
org.drools.rule.builder.dialect.mvel.MVELExprAnalyzer.analyzeExpression(MVELExprAnalyzer.java:114)
org.drools.rule.builder.dialect.mvel.MVELDialect.analyzeBlock(MVELDialect.java:535)
org.drools.rule.builder.dialect.mvel.MVELConsequenceBuilder.build(MVELConsequenceBuilder.java:116)
org.drools.rule.builder.RuleBuilder.build(RuleBuilder.java:103)
org.drools.compiler.PackageBuilder.addRule(PackageBuilder.java:2830)
org.drools.compiler.PackageBuilder.compileRules(PackageBuilder.java:970)
org.drools.compiler.PackageBuilder.compileAllRules(PackageBuilder.java:879)
org.drools.compiler.PackageBuilder.addPackage(PackageBuilder.java:871)
org.drools.compiler.PackageBuilder.addPackageFromDrl(PackageBuilder.java:440)
org.drools.compiler.PackageBuilder.addPackageFromDrl(PackageBuilder.java:418)
droolscompilermultithread.PkgThread.run(PkgThread.java:23)
Can anyone assist on why only 1 thread blocks all the others?
Thanks
///begin code
package droolscompilermultithread;
import java.io.IOException;
import java.io.StringReader;
import org.drools.compiler.DroolsParserException;
import org.drools.compiler.PackageBuilder;
public class Main {
private static int todo = 30000;
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
Main m = new Main();
m.doSingle();
m.doThread(4);
}
private void addHead(StringBuilder sb) {
sb.append("package droolscompilermultithread\n");
sb.append("import Main.MyObject;\n");
}
private void addRule(StringBuilder sb, int id) {
sb.append("rule myRule").append(id).append("\n");
sb.append("dialect \"mvel\"\n");
sb.append("when\n");
sb.append(" $m : MyObject(s1==\"a\")\n");
sb.append("then\n");
sb.append(" $m.s1=\"b\";");
sb.append("end\n\n");
}
/**
* Create a single buffer and compile it all in one thread
* @throws DroolsParserException
* @throws IOException
*/
private void doSingle() throws DroolsParserException, IOException {
StringBuilder sb = new StringBuilder();
addHead(sb);
int count = todo;
while (count-- > 0) {
addRule(sb, count);
}
System.out.println("Starting build size=" + sb.length());
long start = System.currentTimeMillis();
PackageBuilder pkgB = new PackageBuilder();
pkgB.addPackageFromDrl(new StringReader(sb.toString()));
if (pkgB.hasErrors()) {
System.err.println("Errors:" + pkgB.getErrors().toString());
}
long end = System.currentTimeMillis();
System.out.println("Time to compile:" + (end - start) + "
ms");
}
/**
* Create X threads, and in each create a StringBuilder which contains
todo/thread rules
* Then in Threads build each of those packages
* @param threads
* @throws DroolsParserException
* @throws IOException
*/
private void doThread(int threads) throws DroolsParserException,
IOException {
StringBuilder[] sbs = new StringBuilder[threads];
for (int t = 0; t < threads; t++) {
sbs[t] = new StringBuilder();
addHead(sbs[t]);
}
int count = todo;
int threadpos = 0;
while (count-- > 0) {
addRule(sbs[threadpos++], count);
if (threadpos == threads) {
threadpos = 0;
}
}
long start = System.currentTimeMillis();
PkgThread[] thrds = new PkgThread[threads];
for (int t = 0; t < threads; t++) {
thrds[t] = new PkgThread(sbs[t], t);
thrds[t].start();
}
for (int t = 0; t < threads; t++) {
while (thrds[t].isAlive()) {
//Wait for the thread to complete
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
if (thrds[t].pkgB.hasErrors()) {
System.err.println(thrds[t].pkgB.getErrors().toString());
}
}
long end = System.currentTimeMillis();
System.out.println("Time to compile:" + (end - start) + "
ms");
}
/**
* Object used in drools
*/
public class MyObject {
int a;
String s1;
public String getS1() {
return s1;
}
public void setS1(String s1) {
this.s1 = s1;
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
}
/**
* A simple thread that takes a stringbuilder and PackageBuilder it
*/
class PkgThread extends Thread {
StringBuilder sb;
int id;
boolean exception = false;
PackageBuilder pkgB = new PackageBuilder();
long took;
public PkgThread(StringBuilder sb, int id) {
this.sb = sb;
this.id = id;
}
@Override
public void run() {
try {
long start = System.currentTimeMillis();
pkgB.addPackageFromDrl(new StringReader(sb.toString()));
long end = System.currentTimeMillis();
took=end-start;
System.out.println("Thread [" + id + "] compile time="
+
took + " ms");
} catch (Exception ex) {
exception = true;
}
}
public long getTook() {
return took;
}
public boolean isException() {
return exception;
}
public PackageBuilder getPkgB() {
return pkgB;
}
}
/*
*
*
*/
}
//end code
--
View this message in context:
http://drools.46999.n3.nabble.com/Multiple-threads-compiling-rules-is-slo...
Sent from the Drools: User forum mailing list archive at
Nabble.com.