Hi Peter, Thank you for getting back to me. You bring up some interesting points, thanks again!
David On Wed, Feb 18, 2009 at 5:18 PM, Peter Lin <[email protected]> wrote: > 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]. > -------------------------------------------------------------------- > > -------------------------------------------------------------------- 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]. --------------------------------------------------------------------
