Hi Edson, On 7/12/07, Edson Tirelli <[EMAIL PROTECTED]> wrote:
Is it possible for you to provide a test case capable of reproducing the problem?
I've written a quick test case, which is attached. When numberOfThreads==1, everything compiles okay. When numberOfThreads==100, I get function compilation errors and CompileExceptions from mvel. Clearly there is nothing shared between these threads as a new test class is created per thread. If you synchronise the calls to addPackage() and getPackage() using the class monitor i.e. synchronized (DroolsLoadTest.class) { builder.addPackage(packageDescr); builder.getPackage(); } then the problems go away. Hope this helps.
At the same time, I would suggest you to not follow such approach in your application. Compilation is an extremely heavy process and should not be done for each request. The ideal approach is to pre-compile (for instance, we have a contributed ant-task for that) and serialize your rulebase to your database or filesystem, or at least, compile it only once and cache it at runtime.
That's very sensible advice. Our situation is slightly different as users are allowed to change the rules used by a running service, so we need to reflect any changes when a new request comes in. We are planning to apply caching if performance is an issue, but we were trying to assess performance of application under load when this thread safety issue arose. Thanks for your help, Dean.
import org.drools.compiler.DroolsError; import org.drools.compiler.PackageBuilderConfiguration; import org.drools.compiler.PackageBuilderErrors; import org.drools.lang.descr.FunctionDescr; import org.drools.lang.descr.ImportDescr; import org.drools.lang.descr.PackageDescr; public class DroolsLoadTest { public DroolsLoadTest() { } public void runTest() { PackageBuilderConfiguration packageBuilderConfig = new PackageBuilderConfiguration(); org.drools.compiler.PackageBuilder builder = new org.drools.compiler.PackageBuilder(packageBuilderConfig); PackageDescr packageDescr = new PackageDescr("MyRulebase"); addImports(packageDescr); addFunctions(packageDescr); builder.addPackage(packageDescr); builder.getPackage(); if (builder.hasErrors()) { PackageBuilderErrors errors = builder.getErrors(); for (DroolsError error : errors.getErrors()) { System.out.println("ERROR: " + error.getMessage()); } } } private void addImports(PackageDescr packageDescr) { packageDescr.addImport(new ImportDescr("java.util.List")); packageDescr.addImport(new ImportDescr("java.util.ArrayList")); packageDescr.addImport(new ImportDescr("java.util.LinkedList")); packageDescr.addImport(new ImportDescr("java.util.Set")); packageDescr.addImport(new ImportDescr("java.util.HashSet")); packageDescr.addImport(new ImportDescr("java.util.SortedSet")); packageDescr.addImport(new ImportDescr("java.util.TreeSet")); } private void addFunctions(PackageDescr packageDescr) { FunctionDescr functionDescr = new FunctionDescr("foo", "void"); functionDescr.addParameter("String", "arg1"); String body = "Set myHashSet = new HashSet();" + "myHashSet.add(arg1);" + "List myArrayList = new ArrayList();" + "myArrayList.add(arg1);" + "List myLinkedList = new LinkedList();" + "myLinkedList.add(arg1);" + "Set myTreeSet = new TreeSet();" + "myTreeSet.add(arg1);"; functionDescr.setText(body); packageDescr.addFunction(functionDescr); } public static void main(String[] args) { int numberOfThreads = 100; Thread[] threads = new Thread[numberOfThreads]; for (int i = 0; i < numberOfThreads; i++) { Thread testThread = new Thread() { public void run() { DroolsLoadTest test = new DroolsLoadTest(); test.runTest(); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } }; threads[i] = testThread; testThread.start(); } } }
_______________________________________________ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users