A couple of important things to consider. By default drools uses compiled mode, which means it compiles code to pure java when the ruleset is loaded.
To be fair, you'd have to run Drools in interpreted mode and force drools to use mvel to evaluate the mod test. the other option is to write a java function that implements JESS function interface and don't use TESTCE. Instead do something like (Random (x ?x&:(isPrime ?x)) ) the isPrime would be a function that returns true/false Another important thing to consider is that JESS is an expert system shell, whereas drools is a business rule engine. The two are similar, but not comparable on many levels. For example, JESS does type coercion and provide a declarative + functional approach. JESS also has solid support for multi-threaded environments, whereas drools does not in version 4.x. the other important thing to consider is you have to increase the PermGen heap setting to get drools to load more than 15K rules in compiled mode with Sun or IBM JDK. If you need to load 30K rules, drools is going to hit the Perm limit very quickly, whereas JESS will not. peter On Wed, Feb 18, 2009 at 4:28 PM, David Ray <[email protected]> wrote: > Hi, > I am conducting a test of Jess where I am inserting 10,000 rules - > each matching a particular modulus of a prime number and then calling > code to aggregate prime roots of those numbers being matched. The test > submits 100 random numbers one by one - each matching against one of > the 10,000 rules - and the result is timed. It is a test I grabbed > from one of the tests in the drools package which basically stress > tests the rule engine and outputs timing results. I am doing this to > compare the total computation time between Drools and Jess - and Jess > is about 6 times slower, but I think the problem may not be Jess > itself but either how my rules are constructed or some problem where > Jess isn't flushing the I/O stream properly. > > Of particular note are the prepareConstructs() method where the rules > are being built, and the execute() method where the rule engine is > iteratively being invoked. > > I am attaching an executable Jar file which can be run via the > command: java -jar primeNumTest.jar -or- java -cp primeNumTest.jar > PrimeFactorsTest > > Also, I am attaching the two java source files to this message. > Program flow is pretty easy to follow looking at the "main" method in > PrimeFactorsTest.java. > > I am very interested in using Jess and am evaluating its usage for my > company, but this initial test presents some problems... > > Can anyone take a look at this and maybe tell me or point to what the > problem may be? > > I'm a first-time majordomo user, and I seem to have a problem with > posting (I guess > you can't use attachments?) So I'm posting the 2 java source files inline > below, > which can be compiled and run against jess.jar > > Thanks ahead of time, > David > > ==================== > > > > import java.io.BufferedReader; > import java.io.InputStreamReader; > import java.util.Random; > > import jess.JessException; > import jess.Rete; > import jess.Value; > > > /** > * By default, creates 10,000 rules each matching a single prime number - > * then inserts 100 random integers into the engine and collects those > * rules which have fired, and all their roots outputting the timing > * for each stage and each calculation. > * > * See the main() method (at the bottom) for program flow. > * > * @author David Ray > */ > public class PrimeFactorsTest > { > private long seed; > private long start; > private long total; > private int numRules; > private int[] primes; > private int[] randomNumbers; > private Rete rete; > private static long[] timepoint = new long[2]; > > PrimeFactorsTest(int seed) > { > this.seed = seed; > this.rete = new Rete(); > } > > /** > * Generates "numFacts" number of random numbers. > * > * @param numFacts > */ > public void createRandomNums(int numFacts) > { > System.out.println("Generating random number knowledge..."); > Random rand = new Random(seed); > randomNumbers = new int[numFacts]; > start = System.currentTimeMillis(); > for(int i = 0;i < numFacts;i++) { > int nextRand = rand.nextInt(primes[numRules - 1]) + 1; > if(nextRand < 1) {--i; continue;} > randomNumbers[i] = nextRand; > } > total = (System.currentTimeMillis() - start); > System.out.println("Generated "+numFacts+" random numbers in > ["+total+" msecs.]"); > } > > /** > * Inserts a "Jess" formatted command into the Jess Rete engine. > * > * @param statement > * @return Value A jess.Value object representing the > result obtained > * from executing the > specified statement. > */ > public Value insertStatement(String statement) > { > Value retVal = null; > try { > retVal = rete.eval(statement); > }catch(JessException e) { > e.printStackTrace(); > } > return retVal; > } > > /** > * Inserts 10,000 rules into the working memory - each representing > * a "pattern" which will only activate if the LHS is true (meaning > * that the unique prime number correlated with each rule is a prime > * root of the asserted random number). > */ > public void prepareConstructs() > { > ///////////////////////////////////////////// > //Used for debugging > //String statement = "(watch all)"; > //insertStatement(statement); > > System.out.println("-----------------------"); > > System.out.println("Creating New RuleBase..."); > start = System.currentTimeMillis(); > > String statement = "(deftemplate RandomNumber (declare > (from-class > RandomNumber)))"; > insertStatement(statement); > > for(int divisor : primes) > { > statement = "(defrule modulus"+divisor+ > " (RandomNumber (value ?x))" + > " (test (eq 0 (mod ?x "+divisor+")))"+ > "=>"+ > "(call ?a extractRoots "+divisor+"))"; > > insertStatement(statement); > } > > total = (System.currentTimeMillis() - start) / 1000; > System.out.println("Created new RuleBase with "+numRules+" rules > in ["+total+" secs.]"); > } > > /** > * Binds a new RandomNumber object containing a unique random > * number. Then adds the random number fact causing the matching > * rules to activate. Following this, "run" is called to actually > * fire the rules. The "bound" RandomNumber (and the contained > * prime roots) are then printed out and "retract" is called to > * "clear" the working memory of the last fact and the process > * then continues until all RandomNumbers have been processed. > */ > public void execute() > { > System.out.println("-----------------------"); > System.out.println("Starting test..."); > total = 0; > > stopwatch(0); > > for(int randNum : randomNumbers) > { > stopwatch( 1 ); > > String statement = "(bind ?a (new RandomNumber > "+randNum+"))"; > insertStatement(statement); > > //Add a Fact causing Activation to happen here. > statement = "(add ?a)"; > insertStatement(statement); > > //Rule Fire happens here. > statement = "(run)"; > insertStatement(statement); > > statement = "(printout t (call ?a toString) : > "+stopwatch( 1 )+" crlf)"; > insertStatement(statement); > > statement = "(retract 1)"; > insertStatement(statement); > } > > System.out.println("Total Engine Time: " + stopwatch(0)); > } > > /** > * Reads a file containing "numRules" number of prime numbers into > * an array which is later used to generate a unique rule for each > * prime number. > * > * @param numRules > */ > public void loadPrimeList(int numRules) > { > this.numRules = numRules; > BufferedReader buf = null; > try { > buf = new BufferedReader( > new InputStreamReader( > > getClass().getClassLoader().getResourceAsStream("1100000-primes.txt"))); > String line = null; > int count = 0; > System.out.println("Reading "+numRules+" Prime Numbers"); > start = System.currentTimeMillis(); > primes = new int[numRules]; > while((line = buf.readLine()) != null && ((count) < > numRules)) { > primes[count++] = Integer.parseInt(line.trim()); > } > total = (System.currentTimeMillis() - start); > System.out.println("Read "+primes.length+" Prime Numbers > ["+total+" msecs.]"); > } > catch(Exception e) { e.printStackTrace(); } > finally { > try { buf.close(); }catch(Exception ignore) {} > } > } > > /** > * Returns and records time points specified by the index "i" > * passed in. > * > * @param i > * @return message A formatted String containing the > specified time point. > */ > private static String stopwatch(int i) > { > long now = System.currentTimeMillis( ); > String message = " [" + ( now - timepoint[i] ) + " msecs]"; > timepoint[i] = now; > return message; > } > > public static void main(String[] args) > { > int seed = 0; > int numRules = 10000; > int numFacts = 100; > > if(args != null && args.length == 3) { > seed = Integer.parseInt(args[2]); > numRules = Integer.parseInt(args[0]); > numFacts = Integer.parseInt(args[1]); > } > > PrimeFactorsTest pft = new PrimeFactorsTest(seed); > System.out.println("Number of Rules: "+numRules); > System.out.println("Number of Facts: "+numFacts); > System.out.println("Random Seed: "+seed); > > pft.loadPrimeList(numRules); > pft.createRandomNums(numFacts); > > pft.prepareConstructs(); > pft.execute(); > } > } > > =================== > > > > import java.util.ArrayList; > import java.util.List; > > /** > * Stores a random integer value and can extract and store multiples of > * a specified prime root correlated to the original initialized value. > * > * @author davidray > */ > public class RandomNumber { > > Integer value; > int quotient = 1; > List<Integer> primeList = new ArrayList<Integer>(); > > public RandomNumber() {} > > public RandomNumber(Integer number) > { > this.value = number; > this.quotient = number.intValue(); > } > > /** > * Operates on this <code>RandomNumber</code>'s value using the > * specified prime root by extracting the greatest number of the > * specified prime root, saving each root in a list of roots. > * > * @param primeRoot > */ > public void extractRoots(Integer primeRoot) > { > quotient = value.intValue(); > int pFactor = primeRoot.intValue(); > do { > primeList.add(primeRoot); > quotient = quotient / pFactor; > } while(quotient % pFactor == 0); > } > > /** > * Returns the original value with which this > <code>RandomNumber</code> was > * initialized. > * > * @return Integer the original value. > */ > public Integer getValue() > { > return value; > } > > @Override > public int hashCode() { > final int prime = 31; > int result = 1; > result = prime * result + ((value == null) ? 0 : > value.hashCode()); > return result; > } > > @Override > public boolean equals(Object obj) { > if (this == obj) > return true; > if (obj == null) > return false; > if (getClass() != obj.getClass()) > return false; > RandomNumber other = (RandomNumber) obj; > if (value == null) { > if (other.value != null) > return false; > } else if (!value.equals(other.value)) > return false; > return true; > } > > @Override > public String toString() > { > return "Number ("+value+") Prime Numbers: "+primeList; > } > } > > ======================= > > > -------------------------------------------------------------------- > To unsubscribe, send the words 'unsubscribe jess-users [email protected]' > in the BODY of a message to [email protected], NOT to the list > (use your own address!) List problems? Notify [email protected]. > -------------------------------------------------------------------- > > -------------------------------------------------------------------- To unsubscribe, send the words 'unsubscribe jess-users [email protected]' in the BODY of a message to [email protected], NOT to the list (use your own address!) List problems? Notify [email protected]. --------------------------------------------------------------------
