[rules-users] Multiple threads compiling rules is slow

RichardAmbridge richard.ambridge at gmail.com
Fri Jun 28 13:49:30 EDT 2013


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 at 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-slow-tp4024634.html
Sent from the Drools: User forum mailing list archive at Nabble.com.


More information about the rules-users mailing list