[rules-users] Reading DRL file with large number of rules

Edson Tirelli ed.tirelli at gmail.com
Sat Feb 6 10:39:08 EST 2010


    Hi All,

"There is nothing in that which would gain from Drools' Rete algorithm with
its superior "many-patterns-many-object" matching capabilities."

I know Wolfgang knows all this, but I think we need to clarify this
statement for the general public of the list. Assuming all the rules are
indeed like he described (very simple, with a single alpha constraint), then
there are efficient and simple ways to implement it without a rules engine,
but that is not by using "if". At least he would have to use a hashing
technique, or the performance would be roughly linear on number of rules (
O(r) ) when in Drools, that does use hashing techniques for alpha
constraints, it is constant ( O(1) ). Also, it depends on the non-functional
requirements he has, like lifecycle management.

     In any case, I decided to take the bate and implement a quick example
for this. I changed the HelloWorld example in Drools to generate 20k rules
in the same format you have:

rule "rule X"
    dialect "mvel"
when
    Message( message == "X" )
then
    System.out.println( X );
end

    Replacing X by the number of the rule. Then I parse, compile and build a
kbase for these rules and fire the rules for a single object. This is
**NOT** a benchmark, so I am just giving you a rough idea of the hardware...
I am running it on my laptop, with other stuff on. My laptop is a 2-years
old lenovo, dual core, 2Gb memory. I am running with -Xmx1024M.

    Results I got (in ms):

1. Generating Package   ...done. 163 ms
2. Dumping source       ...done. 280897 ms
3. Parsing and compiling...done. 40557 ms
4. Creating kbase       ...done. 79512 ms
5. Firing rules         ...done. 29 ms

    Please note that steps 1 and 2 are the rules generation. You don't have
that, since your source code is ready for processing, right? Step 3 is
executed by the KnowledgeBuilder and step 4 is the
kbase.addKnowledgePackages().

    Again, this is a very simple case showing that it is possible to parse,
compile and load 20k rules quite easily in a drools kbase. Also remember
that kbases are designed to be shared, so you should incur that cost once
and then create sessions (that are really light to create) reusing the
kbase.

    Finally, there are obviously room to improve, since the compilation and
kbase building is single thread today. We want to move to multi-thread
compilation in the future. That should improve things a bit.

   The source code I used is bellow.

   Cheers,
       Edson


public class DroolsTest {

    private static final int NUMBER_OF_RULES = 20000;

    public static final void main(String[] args) {
        try {
            // load up the knowledge base
            KnowledgeBase kbase = readKnowledgeBase();
            StatefulKnowledgeSession ksession =
kbase.newStatefulKnowledgeSession();
            //KnowledgeRuntimeLogger logger =
KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
            // go !
            long ts = System.currentTimeMillis();
            Message message = new Message();
            message.setMessage("5");
            message.setStatus(Message.HELLO);
            ksession.insert(message);
            ksession.fireAllRules();
            System.out.print("5. Firing rules         ...");
            System.out.println("done.
"+(System.currentTimeMillis()-ts)+"ms");
            //logger.close();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    private static KnowledgeBase readKnowledgeBase() throws Exception {
        KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder();

        System.out.print("1. Generating Package   ...");
        long ts = System.currentTimeMillis();
        PackageDescr pkg = generatePackageDescr();
        System.out.println("done. "+(System.currentTimeMillis()-ts)+"ms");

        System.out.print("2. Dumping source       ...");
        ts = System.currentTimeMillis();
        String source = new DrlDumper(  ).dump( pkg );
        //System.out.println(source);
        System.out.println("done. "+(System.currentTimeMillis()-ts)+"ms");

        System.out.print("3. Parsing and compiling...");
        ts = System.currentTimeMillis();
        kbuilder.add(ResourceFactory.newReaderResource( new StringReader(
source ) ), ResourceType.DRL);
        KnowledgeBuilderErrors errors = kbuilder.getErrors();
        if (errors.size() > 0) {
            for (KnowledgeBuilderError error: errors) {
                System.err.println(error);
            }
            throw new IllegalArgumentException("Could not parse
knowledge.");
        }
        System.out.println("done. "+(System.currentTimeMillis()-ts)+"ms");

        System.out.print("4. Creating kbase       ...");
        ts = System.currentTimeMillis();
        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
        System.out.println("done. "+(System.currentTimeMillis()-ts)+"ms");
        return kbase;
    }

    private static PackageDescr generatePackageDescr() {
        PackageDescr result = new PackageDescr("org.drools.test");
        result.addImport( new ImportDescr("com.sample.DroolsTest.Message")
);
        for( int i = 1; i <= NUMBER_OF_RULES; i++ ) {
            RuleDescr rule = new RuleDescr("rule "+i);
            AttributeDescr dialect = new AttributeDescr("dialect", "mvel");
            AndDescr lhs = new AndDescr();
            PatternDescr pat = new PatternDescr("Message");
            FieldConstraintDescr constr = new
FieldConstraintDescr("message");
            LiteralRestrictionDescr restr = new
LiteralRestrictionDescr("==",String.valueOf( i ));
            constr.addRestriction( restr );
            pat.addConstraint( constr );
            lhs.addDescr( pat );
            rule.addAttribute( dialect );
            rule.setLhs( lhs );
            rule.setConsequence( "System.out.println("+i+");\n" );
            result.addRule( rule );
        }
        return result;
    }

    public static class Message {

        public static final int HELLO = 0;
        public static final int GOODBYE = 1;

        private String message;

        private int status;

        public String getMessage() {
            return this.message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public int getStatus() {
            return this.status;
        }

        public void setStatus(int status) {
            this.status = status;
        }

    }

}



2010/2/6 Wolfgang Laun <wolfgang.laun at gmail.com>

> Have you tried increasing the heap size for the JVM?
>
> "20K rules [of the same] simple form" sounds as if you are
> trying to use a hammer where a screwdriver would be appropriate.
> If your description is correct, these 20K rules would be nothing
> but 20K if statements, in disguised form. There is nothing
> in that which would gain from Drools' Rete algorithm with
> its superior "many-patterns-many-object" matching capabilities.
>
> -W
>
> On Sat, Feb 6, 2010 at 12:42 PM, kpowerinfinity
> <kpowerinfinity at gmail.com> wrote:
> > Hello,
> >
> > We are trying to run a DRL file that has more than 20K rules, all of
> > which have the simple form:
> >
> >
> >
> > rule "testpeoplenumber"
> >        salience 100
> >        dialect "mvel"
> >        when
> >                LineItem( inventoryItemCode == "8903210392090")
> > then
> >                InventoryItem fact0 = new InventoryItem();
> >                fact0.setCategoryCode( "ONPROMO" );
> >                insert(fact0 );
> > end
> >
> > However, the rule file is not getting parsed by the builder, and
> > either takes a very long time (well over half an hour), or gives a
> > Heap Overflow exception. We tried with a smaller file (about 1K rules,
> > and the situation is the same).
> >
> > The parsing code is:
> > org.drools.KnowledgeBaseConfiguration kbc =
> > org.drools.KnowledgeBaseFactory.newKnowledgeBaseConfiguration(null,
> > cl);
> >            org.drools.KnowledgeBase kbase =
> > org.drools.KnowledgeBaseFactory.newKnowledgeBase(kbc);
> >                org.drools.builder.KnowledgeBuilderConfiguration
> > knowledgeBuilderConfig =
> >
> org.drools.builder.KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null,
> > cl);
> >            org.drools.builder.KnowledgeBuilder builder =
> > org.drools.builder.KnowledgeBuilderFactory.newKnowledgeBuilder(kbase,
> > knowledgeBuilderConfig);
> >            org.drools.builder.impl.KnowledgeBuilderImpl builderImpl =
> > builder as org.drools.builder.impl.KnowledgeBuilderImpl;
> >
> >
>  builder.add(org.drools.io.ResourceFactory.newFileResource(filename),
> >                    org.drools.builder.ResourceType.DRL);
> >
> > We are using Drools v5. We've tried both with the java jar as well as
> > in .NET (using IKVM to compile it).
> >
> > Any help in understanding why this is happening and how it can be
> > avoided will be appreciated.
> >
> > Warm Regards
> > Krishna.
> >
> > --
> > http://kpowerinfinity.wordpress.com
> > http://www.linkedin.com/in/kpowerinfinity
> > _______________________________________________
> > rules-users mailing list
> > rules-users at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/rules-users
> >
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>



-- 
 Edson Tirelli
 JBoss Drools Core Development
 JBoss by Red Hat @ www.jboss.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20100206/5801ce40/attachment.html 


More information about the rules-users mailing list