[jboss-jira] [JBoss JIRA] Created: (JBRULES-1305) Memory Leak when reusing cached RuleBase and retracting Facts

John Dunning (JIRA) jira-events at lists.jboss.org
Sun Oct 28 10:54:01 EDT 2007


Memory Leak when reusing cached RuleBase and retracting Facts
-------------------------------------------------------------

                 Key: JBRULES-1305
                 URL: http://jira.jboss.com/jira/browse/JBRULES-1305
             Project: JBoss Drools
          Issue Type: Bug
      Security Level: Public (Everyone can see)
    Affects Versions: 4.0.3
         Environment: MacBook, Leopard, Java 1.5 for Mac OSX, Europa, Drools 4.0.2 and 4.0.3
            Reporter: John Dunning


The RuleBase is cached.  A set of approximately 5000 facts are inserted.  As the facts are processed, they are retracted.  Ultimately all facts are retracted.

The rulebase is then re-acquired and the same set of facts are inserted and processed as before.  For the First 100 iterations the jvm free memory (heap) remains consistent, between 100 and 200 iterations the free memory drops by about 1/5th.  After iteration 200 the free memory drops to a constant value, at about 1/20th the original heap size.  Iteration 215 consistently fails with OutOfMemory in both version 4.0.3 and 4.0.2.

The code has been emailed to Mark Proctor, and I can email it over again (contact me on john at tplusplus.net).

The rules are described below:

package net.tplusplus.drools.speedtest.rules.test1;

import net.tplusplus.drools.speedtest.facts.*;
import net.tplusplus.drools.speedtest.bank.*;

rule "Test 01 - Credit Cashflow"
	salience 100
	when
		AccountingPeriod( $start : start, $end : end )
		$cashflow : Cashflow( $account : account, $date : date <= $end && date >= $start, $amount : amount, type==Cashflow.CREDIT )
		not AccountingPeriod( start < $start)
	then 
		//System.out.println("Credit "+$amount);
		$account.setBalance($account.getBalance()+$amount);
		retract($cashflow);
end

rule "Test 01 - Debit Cashflow"
	salience 100
	when
		AccountingPeriod( $start : start, $end : end )
		$cashflow : Cashflow( $account : account, $date : date <= $end && date >= $start, $amount : amount, type==Cashflow.DEBIT )
		not AccountingPeriod( start < $start)
	then 
		//System.out.println("Debit "+$amount);
		$account.setBalance($account.getBalance()+$amount);
		retract($cashflow);
end

rule "Test 01 - Print Balance"
	salience 90
	when
		AccountingPeriod( $start : start, $end : end )
		UpdatingAccount( $accountNo : accountNo, $account : account)
		not AccountingPeriod( start < $start)
	then
		//System.out.print("Period End: "+$end);
		//System.out.println(" - Account "+$accountNo+" - balance: "+$account.getBalance());
end

rule "Test 01 - Retract Period"
	salience 80
	when
		$accountingPeriod : AccountingPeriod( $start : start, $end : end )
		not AccountingPeriod( start < $start)
	then
		retract($accountingPeriod);
end

rule "Test 01 - Retract Remaining AccountingPeriods"
	salience 1
	when
		$fact : AccountingPeriod( )
	then
		retract($fact);
end

rule "Test 01 - Retract Remaining Cashflows"
	salience 1
	when
		$fact : Cashflow( )
	then
		retract($fact);
end

rule "Test 01 - Retract Remaining UpdatingAccounts"
	salience 1
	when
		$fact : UpdatingAccount( )
	then
		retract($fact);
end

The code is as follows:

package net.tplusplus.drools.speedtest.bank;

import net.tplusplus.drools.speedtest.facts.Cashflow;

/**
 * This class provides a simple Bank Account.
 * 
 * @author DunningJ
 *
 */
public class Account
{
	private long accountNo;
	private double balance=0;
	
	public Account(){};
	
	public Account(long accountNo)
	{
		this.accountNo = accountNo;
	}

	public long getAccountNo()
	{
		return accountNo;
	}

	public void setAccountNo(long accountNo)
	{
		this.accountNo = accountNo;
	}

	public double getBalance()
	{
		return balance;
	}

	public void setBalance(double balance)
	{
		this.balance = balance;
	}
	
	/**
	 *  This method enables the comparison of Account objects
	 */	
	@Override
	public boolean equals(Object obj) 
	{
		if(obj==null || !(obj instanceof Cashflow))
		{
			return false;
		}
		
		Account account = (Account) obj;
		
		return (getAccountNo()==account.getAccountNo());
	}	
	
	public String toString()
	{
		return "Account[" 
				+"accountNo="+accountNo
				+",balance="+balance
				+"]";
	}
}


package net.tplusplus.drools.speedtest.facts;

import java.util.Date;

import net.tplusplus.rules.runner.rao.Fact;

/**
 * Each bank transaction must fall within an AccountingPeriod - which
 * is normally a quarter.  A separate AccountingPeriod fact is passed to the
 * Drools engine for each accounting period for which we are processing 
 * calculations.
 * 
 * @author DunningJ
 *
 */
public class AccountingPeriod implements Fact, Comparable<AccountingPeriod>
{
	private Date start;
	private long startl;
	private Long startL;
	private Date end;
	private long endl;
	private Long endL;
	
	public AccountingPeriod(){}
	
	public AccountingPeriod(Date start, Date end)
	{
		this.start = start;
		this.startl = start.getTime();
		this.startL = start.getTime();
		this.end = end;
		this.endl = end.getTime();
		this.endL = end.getTime();
	}

	public Date getStart()
	{
		return start;
	}
	
	public long getStartl()
	{
		return startl;
	}
	
	public long getStartL()
	{
		return startL;
	}

	public void setStart(Date start)
	{
		this.start = start;
	}

	public Date getEnd()
	{
		return end;
	}

	public long getEndl()
	{
		return endl;
	}
	
	public Long getEndL()
	{
		return endL;
	}

	public void setEnd(Date end)
	{
		this.end = end;
	}
	
	/**
	 *  This method enables the Collections api to sort the 
	 *  AccountingPeriod by period start date.
	 */
	public int compareTo(AccountingPeriod accountingPeriod)
	{
		if(this.start.after(accountingPeriod.getStart()))
		{
			return 1;
		}
		if(this.start.before(accountingPeriod.getStart()))
		{
			return -1;
		}	
		
		return 0;
	}	
	
	/**
	 *  This method enables the comparison of AccountingPeriod objects
	 */	
	@Override
	public boolean equals(Object obj) 
	{
		if(obj==null || !(obj instanceof AccountingPeriod))
		{
			return false;
		}
		
		AccountingPeriod ap = (AccountingPeriod) obj;
		
		return getStart().equals(ap.getStart());
	}

	public String toString()
	{
		return "AccountingPeriod[" 
				+"start="+start
				+",end="+end
				+"]";
	}
}


package net.tplusplus.drools.speedtest.facts;

import java.util.Date;

import net.tplusplus.drools.speedtest.bank.Account;
import net.tplusplus.rules.runner.rao.Fact;


public class Cashflow implements Fact, Comparable<Cashflow>
{	
	public static final int CREDIT = 0;
	public static final int DEBIT = 1;
	
	private Date date;
	private long datel;
	private Long dateL;
	private double amount;
	private int type;
	private Account account;
	
	public Cashflow()
	{
	}
	
	public Cashflow(Date date, double amount, int type, Account account)
	{
		this();
		
		this.date = date;
		this.datel= date.getTime();
		this.dateL = date.getTime();
		this.amount = amount;
		this.type = type;
		this.account = account;
	}

	public Date getDate()
	{
		return date;
	}
	
	public void setDate(Date date)
	{
		this.date = date;
	}
	
	public double getAmount()
	{
		return amount;
	}
	
	public void setAmount(double amount)
	{
		this.amount = amount;
	}
	
	public int getType()
	{
		return type;
	}

	public void setType(int type)
	{
		this.type = type;
	}

	public Account getAccount()
	{
		return account;
	}

	public void setAccount(Account account)
	{
		this.account = account;
	}
	
	public long getDatel()
	{
		return datel;
	}
	
	public long getDateL()
	{
		return dateL;
	}
	
	/**
	 *  This method enables the Collections api to sort the 
	 *  Cashflow by cashflow date.
	 */	
	public int compareTo(Cashflow cashflow)
	{
		if(getDate().after(cashflow.getDate()))
		{
			return 1;
		}
		if(getDate().before(cashflow.getDate()))
		{
			return -1;
		}	
		
		return 0;
	}
	
	/**
	 *  This method enables the comparison of Cashflow objects
	 */	
	@Override
	public boolean equals(Object obj) 
	{
		if(obj==null || !(obj instanceof Cashflow))
		{
			return false;
		}
		
		Cashflow cashflow = (Cashflow) obj;
		
		if(!getAccount().equals(cashflow.getAccount())) return false;
		if(getAmount()!=cashflow.getAmount()) return false;
		if(!getDate().equals(cashflow.getDate())) return false;
		if(getType()!=cashflow.getType()) return false;
		
		return true;
	}	
	
	public String toString()
	{
		return "Cashflow["
				//+"account="+account
				+"date="+date
				+",amount="+amount
				+",type="+(type==CREDIT?"Credit":"Debit")
				+"]";
	}
	
	
}


package net.tplusplus.drools.speedtest.facts;

import net.tplusplus.drools.speedtest.bank.Account;
import net.tplusplus.rules.runner.rao.Fact;


public class UpdatingAccount implements Fact, Comparable<UpdatingAccount>
{
	private long accountNo;
	private Account account;
	
	public UpdatingAccount(long accountNo, Account account)
	{
		this.accountNo = accountNo;
		this.account = account;
	}

	public long getAccountNo()
	{
		return accountNo;
	}

	public void setAccountNo(long accountNo)
	{
		this.accountNo = accountNo;
	}

	public Account getAccount()
	{
		return account;
	}

	public void setAccount(Account account)
	{
		this.account = account;
	}
	
	/**
	 *  This method enables the Collections api to sort the 
	 *  UpdatingAccount by account no.
	 */	
	public int compareTo(UpdatingAccount updatingAccount)
	{
		if(getAccountNo()==updatingAccount.getAccountNo()) return 0;
		
		return (getAccountNo()>updatingAccount.getAccountNo()) ? 1 : -1;
	}
	
	/**
	 *  This method enables the comparison of UpdatingAccount objects
	 */	
	@Override
	public boolean equals(Object obj) 
	{
		if(obj==null || !(obj instanceof UpdatingAccount))
		{
			return false;
		}
		
		UpdatingAccount updatingAccount = (UpdatingAccount) obj;
		
		return (getAccountNo()==updatingAccount.getAccountNo());	
	}		
}


package net.tplusplus.test.drools.speedtest.data;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import net.tplusplus.drools.speedtest.bank.Account;
import net.tplusplus.drools.speedtest.facts.AccountingPeriod;
import net.tplusplus.drools.speedtest.facts.Cashflow;
import net.tplusplus.drools.speedtest.facts.UpdatingAccount;
import net.tplusplus.rules.runner.rao.Fact;
import net.tplusplus.utils.SimpleDate;


public class TestData
{
	private static Date startDate;
	private static Date endDate;
	
	private static List<Account> accounts;
	private static List<UpdatingAccount> updatingAccounts;
	private static List<Cashflow> cashflows;
	private static List<AccountingPeriod> accountingPeriods;
	
	static
	{
		try
		{
			startDate = new SimpleDate("01/01/2007");
			endDate = new SimpleDate("31/12/2007");
		}
		catch(Exception e){}
	}
	
	private static List<Account> getAllAccounts()
	{
		if(accounts==null)
		{
			accounts = new ArrayList<Account>();
		
			accounts.add(new Account(1));
		}
		
		return accounts;
	}
	
	public static List<UpdatingAccount> getAllUpdatingAccounts()
	{
		if(updatingAccounts==null)
		{
			updatingAccounts = new ArrayList<UpdatingAccount>();
			
			for(Account account : getAllAccounts())
			{
				updatingAccounts.add(new UpdatingAccount(account.getAccountNo(), account));
			}
		}
		
		return updatingAccounts;
	}
	
	public static List<Cashflow> getAllCashflows()
	throws Exception
	{
		if(cashflows==null)
		{
			cashflows = new ArrayList<Cashflow>();		
				
			for(Date date = startDate; !date.after(endDate);)
			{
				int adj = 0;
				
				for(Account acct : getAllAccounts())
				{
					adj++;
					
					int[] credits = new int[]{ 300, 150, 200, 50, 120, 20, 10};
					int[] debits = new int[]{ 200, 50, 50, 30};
					
					for(int credit : credits)
					{
						Cashflow c = new Cashflow(date, credit+adj, Cashflow.CREDIT, acct);
						cashflows.add(c);
					}
					
					for(int debit : debits)
					{
						Cashflow c = new Cashflow(date, debit+adj, Cashflow.DEBIT, acct);		
						cashflows.add(c);
					}	
				}
				
				long newDate = date.getTime() + 24l*60l*60l*1000l;
				date = new Date(newDate);
			}
		}
		
		return cashflows;
	}
	
	public static List<AccountingPeriod> getAccountingPeriods()
	throws Exception
	{
		if(accountingPeriods==null)
		{
			accountingPeriods = new ArrayList<AccountingPeriod>();
			
			accountingPeriods.add(new AccountingPeriod(new SimpleDate("01/01/2007"),new SimpleDate("31/03/2007")));
			accountingPeriods.add(new AccountingPeriod(new SimpleDate("01/04/2007"),new SimpleDate("30/06/2007")));
			accountingPeriods.add(new AccountingPeriod(new SimpleDate("01/07/2007"),new SimpleDate("30/09/2007")));
			accountingPeriods.add(new AccountingPeriod(new SimpleDate("01/10/2007"),new SimpleDate("31/12/2007")));
		}
		
		return accountingPeriods;
	}
	
	public static List<Fact> getAllFacts()
	throws Exception
	{
		List<Fact> facts = new ArrayList<Fact>();
		
		facts.addAll(getAccountingPeriods());
		facts.addAll(getAllCashflows());
		facts.addAll(getAllUpdatingAccounts());
		
		return facts;		
	}
	
	public static void resetAccounts()
	{
		for(Account account : getAllAccounts())
		{
			account.setBalance(0);
		}
	}
}


package net.tplusplus.test.drools.speedtest;

import java.util.List;

import org.drools.RuleBase;
import org.drools.WorkingMemory;

import net.tplusplus.rules.runner.RuleRunner;
import net.tplusplus.rules.runner.rao.Fact;
import net.tplusplus.test.drools.speedtest.data.TestData;
import net.tplusplus.utils.TimedResults;


public class SpeedTest1
{
	public static void main(String[] args)
	throws Exception
	{
		int iterations = 1000;
		
		//runTest1(iterations);
		runTest2(iterations);
		runTest3(iterations);
		runTest4(iterations);
		runTest5(iterations);
		runTest6(iterations);

	}
	
	public static void runTest1(int iterations)
	throws Exception
	{		
		System.out.println("\nRunning Speed Test 1 - NO CACHING");
		TimedResults results = new TimedResults();
		
		RuleRunner runner = new RuleRunner();
		runner.addRules("/net/tplusplus/drools/speedtest/rules/test1/test01.drl");
		
		List<Fact> allFacts = TestData.getAllFacts();
		runner.addFacts(allFacts);

		for(int i=0;i<iterations;i++)
		{
			TestData.resetAccounts();
			
			long starttime = System.currentTimeMillis();
			
			runner.createRuleBase();
			runner.createWorkingMemory();
			runner.runRules();
			
			long endtime = System.currentTimeMillis();
			long timetaken = endtime - starttime;
			
			results.addTime(timetaken);
		}
		
		System.out.println("Iterations: "+iterations);
		System.out.println("Number of facts: "+runner.getFacts().size());
		System.out.println("fastest time: "+results.getFastest()+" (ms)");
		System.out.println("slowest time: "+results.getSlowest()+" (ms)");
		System.out.println("average time: "+results.getAverage()+" (ms)");
	}
	
	public static void runTest2(int iterations)
	throws Exception
	{		
		System.out.println("\nRunning Speed Test 2 - CACHING RULEBASE");
		TimedResults results = new TimedResults();
		
		RuleRunner runner = new RuleRunner();
		runner.addRules("/net/tplusplus/drools/speedtest/rules/test1/test01.drl");
		
		List<Fact> allFacts = TestData.getAllFacts();
		runner.addFacts(allFacts);

		RuleBase cachedRuleBase = null;
		
		for(int i=0;i<iterations;i++)
		{
			System.out.println(i);
			TestData.resetAccounts();
			
			long starttime = System.currentTimeMillis();
			
			if(cachedRuleBase==null)
			{
				runner.createWorkingMemory();
			}
			else
			{
				runner.setRuleBase(cachedRuleBase);
				runner.createWorkingMemory();
			}
			
			runner.runRules();
			long endtime = System.currentTimeMillis();
			long timetaken = endtime - starttime;
			
			results.addTime(timetaken);
		}
		
		System.out.println("Iterations: "+iterations);
		System.out.println("Number of facts: "+runner.getFacts().size());
		System.out.println("fastest time: "+results.getFastest()+" (ms)");
		System.out.println("slowest time: "+results.getSlowest()+" (ms)");
		System.out.println("average time: "+results.getAverage()+" (ms)");
	}
	
	public static void runTest3(int iterations)
	throws Exception
	{		
		System.out.println("\nRunning Speed Test 3 - CACHING WORKINGSTORE");
		TimedResults results = new TimedResults();
		
		RuleRunner runner = new RuleRunner();
		runner.addRules("/net/tplusplus/drools/speedtest/rules/test1/test01.drl");
		
		List<Fact> allFacts = TestData.getAllFacts();
		runner.addFacts(allFacts);

		WorkingMemory cachedWorkingMemory = null;
		
		for(int i=0;i<iterations;i++)
		{
			TestData.resetAccounts();
			
			long starttime = System.currentTimeMillis();
			
			if(cachedWorkingMemory==null)
			{
				runner.createWorkingMemory();
			}
			else
			{
				runner.setWorkingMemory(cachedWorkingMemory);
			}
			
			runner.runRules();
			long endtime = System.currentTimeMillis();
			long timetaken = endtime - starttime;
			
			results.addTime(timetaken);
		}
		
		System.out.println("Iterations: "+iterations);
		System.out.println("Number of facts: "+runner.getFacts().size());
		System.out.println("fastest time: "+results.getFastest()+" (ms)");
		System.out.println("slowest time: "+results.getSlowest()+" (ms)");
		System.out.println("average time: "+results.getAverage()+" (ms)");
	}	
	
	public static void runTest4(int iterations)
	throws Exception
	{		
		System.out.println("\nRunning Speed Test 4 - OPTIMISED DRL - changed order of facts");
		TimedResults results = new TimedResults();
		
		RuleRunner runner = new RuleRunner();
		runner.addRules("/net/tplusplus/drools/speedtest/rules/test1/test02.drl");
		
		List<Fact> allFacts = TestData.getAllFacts();
		runner.addFacts(allFacts);

		WorkingMemory cachedWorkingMemory = null;
		
		for(int i=0;i<iterations;i++)
		{
			TestData.resetAccounts();
			
			long starttime = System.currentTimeMillis();
			
			if(cachedWorkingMemory==null)
			{
				runner.createWorkingMemory();
			}
			else
			{
				runner.setWorkingMemory(cachedWorkingMemory);
			}
			
			runner.runRules();
			long endtime = System.currentTimeMillis();
			long timetaken = endtime - starttime;
			
			results.addTime(timetaken);
		}
		
		System.out.println("Iterations: "+iterations);
		System.out.println("Number of facts: "+runner.getFacts().size());
		System.out.println("fastest time: "+results.getFastest()+" (ms)");
		System.out.println("slowest time: "+results.getSlowest()+" (ms)");
		System.out.println("average time: "+results.getAverage()+" (ms)");
	}	
	
	public static void runTest5(int iterations)
	throws Exception
	{		
		System.out.println("\nRunning Speed Test 5 - OPTIMISED DRL - using long instead of Date");
		TimedResults results = new TimedResults();
		
		RuleRunner runner = new RuleRunner();
		runner.addRules("/net/tplusplus/drools/speedtest/rules/test1/test03.drl");
		
		List<Fact> allFacts = TestData.getAllFacts();
		runner.addFacts(allFacts);

		WorkingMemory cachedWorkingMemory = null;
		
		for(int i=0;i<iterations;i++)
		{
			TestData.resetAccounts();
			
			long starttime = System.currentTimeMillis();
			
			if(cachedWorkingMemory==null)
			{
				runner.createWorkingMemory();
			}
			else
			{
				runner.setWorkingMemory(cachedWorkingMemory);
			}
			
			runner.runRules();
			long endtime = System.currentTimeMillis();
			long timetaken = endtime - starttime;
			
			results.addTime(timetaken);
		}
		
		System.out.println("Iterations: "+iterations);
		System.out.println("Number of facts: "+runner.getFacts().size());
		System.out.println("fastest time: "+results.getFastest()+" (ms)");
		System.out.println("slowest time: "+results.getSlowest()+" (ms)");
		System.out.println("average time: "+results.getAverage()+" (ms)");
	}
	
	public static void runTest6(int iterations)
	throws Exception
	{		
		System.out.println("\nRunning Speed Test 6 - OPTIMISED DRL - using Long instead of Date");
		TimedResults results = new TimedResults();
		
		RuleRunner runner = new RuleRunner();
		runner.addRules("/net/tplusplus/drools/speedtest/rules/test1/test04.drl");
		
		List<Fact> allFacts = TestData.getAllFacts();
		runner.addFacts(allFacts);

		WorkingMemory cachedWorkingMemory = null;
		
		for(int i=0;i<iterations;i++)
		{
			TestData.resetAccounts();
			
			long starttime = System.currentTimeMillis();
			
			if(cachedWorkingMemory==null)
			{
				runner.createWorkingMemory();
			}
			else
			{
				runner.setWorkingMemory(cachedWorkingMemory);
			}
			
			runner.runRules();
			long endtime = System.currentTimeMillis();
			long timetaken = endtime - starttime;
			
			results.addTime(timetaken);
		}
		
		System.out.println("Iterations: "+iterations);
		System.out.println("Number of facts: "+runner.getFacts().size());
		System.out.println("fastest time: "+results.getFastest()+" (ms)");
		System.out.println("slowest time: "+results.getSlowest()+" (ms)");
		System.out.println("average time: "+results.getAverage()+" (ms)");
	}
}


package net.tplusplus.rules.runner;

import java.io.File;
import java.io.FileReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Iterator;

import net.tplusplus.rules.runner.rao.Fact;
import net.tplusplus.rules.runner.rao.Global;

import org.drools.FactHandle;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.WorkingMemory;
import org.drools.compiler.PackageBuilder;
import org.drools.spi.ActivationGroup;
import org.drools.spi.AgendaGroup;


public class RuleRunner
{
	private RuleBase ruleBase;
	private WorkingMemory workingMemory;
	
	private List<String> rules;
	private List<Global> globals;
	private List<Fact> facts;
	
	public RuleRunner()
	{
		rules = new ArrayList<String>();
		globals = new ArrayList<Global>();
		facts = new ArrayList<Fact>();	
	}
	
	public void addRules(String... rules)
	{
		this.rules.addAll(Arrays.asList(rules));
	}
	
	public void addGlobals(Global... globals)
	{
		this.globals.addAll(Arrays.asList(globals));
	}
	
	public void addFacts(Fact... facts)
	{
		this.facts.addAll(Arrays.asList(facts));
	}
	
	public void addFacts(List<? extends Fact> facts)
	{
		this.facts.addAll(facts);
	}	
	
	public List<Fact> getFacts()
	{
		return this.facts;
	}
	
	public void clearFacts()
	{
		this.facts = new ArrayList<Fact>();
	}
	
	public RuleBase createRuleBase()
	throws Exception
	{
		if(rules==null)
		{
			throw new Exception("No rules provided for Engine");
		}
		
		ruleBase = RuleBaseFactory.newRuleBase();
		PackageBuilder builder = new PackageBuilder();		
		
		for(String ruleFile : rules)
		{
			URL resource = this.getClass().getResource(ruleFile);
			
			if(resource==null)
			{
				System.err.println("Could not find resource: "+ruleFile);
				continue;
			}

			File file = new File(this.getClass().getResource(ruleFile).getPath());
			if(!file.exists())
			{
				System.err.println("Could not find rule file: "+file.getPath());
				continue;
			}
			
			builder.addPackageFromDrl(new FileReader(file.getPath()));
		}
		
		org.drools.rule.Package pkg = builder.getPackage();		
		ruleBase.addPackage(pkg);	
		
		return ruleBase;
	}
	
	public void setRuleBase(RuleBase ruleBase)
	{
		this.ruleBase = ruleBase;
	}
	
	public RuleBase getRuleBase()
	{
		return ruleBase;
	}
	
	public WorkingMemory createWorkingMemory()
	throws Exception
	{
		if(ruleBase==null)
		{
			createRuleBase();
		}
		
		workingMemory = null;
		
		workingMemory = ruleBase.newStatefulSession();
		
		return workingMemory;
	}
	
	public void setWorkingMemory(WorkingMemory workingMemory)
	{
		this.workingMemory = workingMemory;
	}
	
	public WorkingMemory getWorkingMemory()
	{
		return workingMemory;
	}
	
	public void runRules()
	throws Exception
	{		
		if(workingMemory==null)
		{
			throw new Exception("No workingMemory created for Engine");
		}
		
		System.gc();
		System.out.println("Free Memory: "+Runtime.getRuntime().freeMemory());
		
		
		if(globals!=null)
		{
			for(Global global : globals)
			{
				workingMemory.setGlobal(global.getName(), global.getValue());
			}
		}

		if(facts!=null)
		{
			for(Fact fact : facts)
			{
				workingMemory.insert(fact);
			}
		}

		workingMemory.fireAllRules();
	}
}


package net.tplusplus.rules.runner.rao;

public interface Fact
{

}


package net.tplusplus.rules.runner.rao;

public class Global
{
	private String name;
	private Object value;
	
	public Global(String name, Object value)
	{
		this.name = name;
		this.value = value;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public Object getValue()
	{
		return value;
	}

	public void setValue(Object value)
	{
		this.value = value;
	}
	
	public String toString()
	{
		return "Global["
				+"name="+name
				+"value="+value
				+"]";
	}
}


package net.tplusplus.utils;

import java.text.SimpleDateFormat;
import java.util.Date;

public class SimpleDate extends Date
{
	public static final long serialVersionUID = 1;
	
	public SimpleDate(String datestr)
	throws Exception
	{
		SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
		this.setTime(format.parse(datestr).getTime());
	}
}


package net.tplusplus.utils;

import java.util.HashMap;
import java.util.Map;

public class TimedResults
{
	private long fastest = -1;
	private long slowest = -1;
	
	private Map<Long,Long> results = new HashMap<Long,Long>();
	
	public TimedResults()
	{
	}
	
	public void addTime(long time)
	throws Exception
	{
		if(time < 0)
		{
			throw new Exception("Invalid Time");
		}
		
		Long key = System.currentTimeMillis();
		results.put(key,time);
		
		if(fastest==-1 || fastest>time) fastest=time;
		if(slowest==-1 || slowest<time) slowest=time;
	}
	
	public Map<Long,Long> getResults()
	{
		return results;
	}
	
	public long getFastest()
	{
		return fastest;
	}
	
	public long getSlowest()
	{
		return slowest;
	}
	
	public long getAverage()
	{
		long time = 0;
		
		for(Long timetaken : results.values())
		{
			time += timetaken;
		}
		
		return time / results.size();
	}
}



-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the jboss-jira mailing list