瀏覽代碼

为条件匹配添加缓存,提高规则计算性能

youseries 7 年之前
父節點
當前提交
3164a244e2

+ 60 - 48
urule-core/src/main/java/com/bstek/urule/model/rule/lhs/Criteria.java

@@ -27,7 +27,6 @@ import com.bstek.urule.model.library.Datatype;
 import com.bstek.urule.model.rule.Op;
 import com.bstek.urule.model.rule.SimpleArithmetic;
 import com.bstek.urule.model.rule.Value;
-import com.bstek.urule.runtime.assertor.AssertorEvaluator;
 import com.bstek.urule.runtime.rete.EvaluationContext;
 import com.bstek.urule.runtime.rete.ValueCompute;
 
@@ -44,72 +43,85 @@ public class Criteria extends BaseCriterion implements BaseCriteria{
 	
 	@Override
 	public EvaluateResponse evaluate(EvaluationContext context,Object obj,List<Object> allMatchedObjects){
-		Object leftValue=null;
 		Datatype datatype=null;
+		Object leftResult=null;
 		LeftPart leftPart=left.getLeftPart();
-		if(leftPart instanceof VariableLeftPart){
-			VariableLeftPart varPart=(VariableLeftPart)leftPart;
-			datatype=varPart.getDatatype();
-			if(varPart.getVariableName()==null){
-				throw new RuleException("Criteria left[variableName] can not be null.");
+		String leftId=left.getId();
+		ValueCompute valueCompute=context.getValueCompute();
+		if(context.partValueExist(leftId)){
+			leftResult=context.getPartValue(leftId);
+			if(leftPart instanceof VariableLeftPart){
+				datatype=((VariableLeftPart)leftPart).getDatatype();
 			}
-			leftValue=Utils.getObjectProperty(obj, varPart.getVariableName());
 		}else{
-			if(leftPart instanceof MethodLeftPart){
-				MethodLeftPart methodPart=(MethodLeftPart)leftPart;
-				ExecuteMethodAction methodAction=new ExecuteMethodAction();
-				methodAction.setBeanId(methodPart.getBeanId());
-				methodAction.setBeanLabel(methodPart.getBeanLabel());
-				methodAction.setMethodLabel(methodPart.getMethodLabel());
-				methodAction.setMethodName(methodPart.getMethodName());
-				methodAction.setParameters(methodPart.getParameters());
-				ActionValue actionValue=methodAction.execute(context, obj,allMatchedObjects,null);
-				if(actionValue==null){
-					leftValue=null;
-				}else{
-					leftValue=actionValue.getValue();
+			Object leftValue=null;
+			if(leftPart instanceof VariableLeftPart){
+				VariableLeftPart varPart=(VariableLeftPart)leftPart;
+				datatype=varPart.getDatatype();
+				if(varPart.getVariableName()==null){
+					throw new RuleException("Criteria left[variableName] can not be null.");
+				}
+				leftValue=Utils.getObjectProperty(obj, varPart.getVariableName());
+			}else{
+				if(leftPart instanceof MethodLeftPart){
+					MethodLeftPart methodPart=(MethodLeftPart)leftPart;
+					ExecuteMethodAction methodAction=new ExecuteMethodAction();
+					methodAction.setBeanId(methodPart.getBeanId());
+					methodAction.setBeanLabel(methodPart.getBeanLabel());
+					methodAction.setMethodLabel(methodPart.getMethodLabel());
+					methodAction.setMethodName(methodPart.getMethodName());
+					methodAction.setParameters(methodPart.getParameters());
+					ActionValue actionValue=methodAction.execute(context, obj,allMatchedObjects,null);
+					if(actionValue==null){
+						leftValue=null;
+					}else{
+						leftValue=actionValue.getValue();
+					}
+				}else if(leftPart instanceof ExistLeftPart){
+					ExistLeftPart existPart=(ExistLeftPart)leftPart;
+					leftValue=existPart.evaluate(context, obj, allMatchedObjects);
+				}else if(leftPart instanceof AllLeftPart){
+					AllLeftPart allPart=(AllLeftPart)leftPart;
+					leftValue=allPart.evaluate(context, obj, allMatchedObjects);
+				}else if(leftPart instanceof CollectLeftPart){
+					CollectLeftPart collectPart=(CollectLeftPart)leftPart;
+					leftValue=collectPart.evaluate(context, obj, allMatchedObjects);
+				}else if(leftPart instanceof CommonFunctionLeftPart){
+					CommonFunctionLeftPart part=(CommonFunctionLeftPart)leftPart;
+					leftValue=part.evaluate(context, obj, allMatchedObjects);
 				}
-			}else if(leftPart instanceof ExistLeftPart){
-				ExistLeftPart existPart=(ExistLeftPart)leftPart;
-				leftValue=existPart.evaluate(context, obj, allMatchedObjects);
-			}else if(leftPart instanceof AllLeftPart){
-				AllLeftPart allPart=(AllLeftPart)leftPart;
-				leftValue=allPart.evaluate(context, obj, allMatchedObjects);
-			}else if(leftPart instanceof CollectLeftPart){
-				CollectLeftPart collectPart=(CollectLeftPart)leftPart;
-				leftValue=collectPart.evaluate(context, obj, allMatchedObjects);
-			}else if(leftPart instanceof CommonFunctionLeftPart){
-				CommonFunctionLeftPart part=(CommonFunctionLeftPart)leftPart;
-				leftValue=part.evaluate(context, obj, allMatchedObjects);
 			}
-			datatype=Utils.getDatatype(leftValue);
-		}
-		Object leftResult=leftValue;
-		SimpleArithmetic arithmetic=left.getArithmetic();
-		ValueCompute valueCompute=context.getValueCompute();
-		if(arithmetic!=null){
-			leftResult=valueCompute.simpleArithmeticCompute(context,leftValue, arithmetic);
+			leftResult=leftValue;
+			SimpleArithmetic arithmetic=left.getArithmetic();
+			if(arithmetic!=null){
+				leftResult=valueCompute.simpleArithmeticCompute(context,leftValue, arithmetic);
+			}
+			context.storePartValue(leftId, leftResult);
 		}
 		EvaluateResponse response=new EvaluateResponse();
 		response.setLeftResult(leftResult);
 		Object right=null;
 		if(value!=null){
-			right=valueCompute.complexValueCompute(value,obj,context,allMatchedObjects,null);
-			response.setRightResult(right);
-			if(right==null){
-				response.setResult(false);
-				return response;
+			String valueId=value.getId();
+			if(context.partValueExist(valueId)){
+				right=context.getPartValue(valueId);
+			}else{				
+				right=valueCompute.complexValueCompute(value,obj,context,allMatchedObjects,null);
+				response.setRightResult(right);
+				context.storePartValue(valueId, right);
 			}
 		}
-		AssertorEvaluator assertorEvaluator=context.getAssertorEvaluator();
-		boolean result=assertorEvaluator.evaluate(leftResult, right, datatype,op);
+		if(datatype==null){
+			datatype=Utils.getDatatype(leftResult);
+		}
+		boolean result=context.getAssertorEvaluator().evaluate(leftResult, right, datatype,op);
 		response.setResult(result);
 		return response;
 	}
 	@Override
 	public String getId() {
 		if(id==null){
-			id=left.getLeftPart().getId()+"【"+op.toString()+"】";
+			id=left.getId()+"【"+op.toString()+"】";
 			if(value!=null)id+=value.getId();
 		}
 		return id;

+ 10 - 0
urule-core/src/main/java/com/bstek/urule/model/rule/lhs/Left.java

@@ -22,6 +22,7 @@ import com.bstek.urule.model.rule.SimpleArithmetic;
  * @since 2014年12月29日
  */
 public class Left {
+	private String id;
 	private LeftPart leftPart;
 	private LeftType type;
 	private SimpleArithmetic arithmetic;
@@ -43,4 +44,13 @@ public class Left {
 	public void setType(LeftType type) {
 		this.type = type;
 	}
+	public String getId(){
+		if(id==null){
+			id=leftPart.getId();
+			if(arithmetic!=null){
+				id=id+arithmetic.getId();
+			}
+		}
+		return id;
+	}
 }

+ 2 - 0
urule-core/src/main/java/com/bstek/urule/runtime/KnowledgeSessionImpl.java

@@ -205,6 +205,7 @@ public class KnowledgeSessionImpl implements KnowledgeSession{
 		for(Object fact:facts){
 			evaluationRete(fact);
 		}
+		evaluationContext.clean();
 		buildElseRules(true);
 		ExecutionResponseImpl resp=(ExecutionResponseImpl)agenda.execute(filter,max);
 		resp.setDuration(System.currentTimeMillis()-start);
@@ -336,6 +337,7 @@ public class KnowledgeSessionImpl implements KnowledgeSession{
 		}
 		evaluationRete(obj);
 		buildElseRules(false);
+		evaluationContext.clean();
 	}
 	
 	private void evaluationRete(Object fact) {

+ 9 - 1
urule-core/src/main/java/com/bstek/urule/runtime/rete/CriteriaActivity.java

@@ -44,7 +44,15 @@ public class CriteriaActivity  extends AbstractActivity {
 			return null;
 		}
 		List<Object> allMatchedObjects=new ArrayList<Object>();
-		EvaluateResponse response=criteria.evaluate(context, obj,allMatchedObjects);
+		EvaluateResponse response=null;
+		String criteriaId=criteria.getId();
+		Object storeValue=context.getCriteriaValue(criteriaId);
+		if(storeValue!=null){
+			response=(EvaluateResponse)storeValue;
+		}else{
+			response=criteria.evaluate(context,obj,allMatchedObjects);
+			context.storeCriteriaValue(criteriaId, response);;
+		}
 		boolean result=response.getResult();
 		doDebug(response,context);
 		if(result){

+ 5 - 0
urule-core/src/main/java/com/bstek/urule/runtime/rete/EvaluationContext.java

@@ -23,4 +23,9 @@ package com.bstek.urule.runtime.rete;
 public interface EvaluationContext extends Context {
 	Activity getPrevActivity();
 	void setPrevActivity(Activity activity);
+	Object getCriteriaValue(String id);
+	Object getPartValue(String id);
+	void storeCriteriaValue(String id,Object obj);
+	void storePartValue(String id,Object obj);
+	boolean partValueExist(String id);
 }

+ 33 - 0
urule-core/src/main/java/com/bstek/urule/runtime/rete/EvaluationContextImpl.java

@@ -15,6 +15,7 @@
  ******************************************************************************/
 package com.bstek.urule.runtime.rete;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -29,6 +30,8 @@ import com.bstek.urule.runtime.WorkingMemory;
  */
 public class EvaluationContextImpl extends ContextImpl implements EvaluationContext {
 	private Activity prevActivity;
+	private Map<String,Object> criteriaValueMap=new HashMap<String,Object>();
+	private Map<String,Object> partValueMap=new HashMap<String,Object>();
 	public EvaluationContextImpl(WorkingMemory workingMemory,
 			ApplicationContext applicationContext, 
 			Map<String, String> variableCategoryMap,List<MessageItem> debugMessageItems) {
@@ -42,4 +45,34 @@ public class EvaluationContextImpl extends ContextImpl implements EvaluationCont
 	public void setPrevActivity(Activity activity) {
 		this.prevActivity=activity;
 	}
+	@Override
+	public Object getCriteriaValue(String id) {
+		if(!criteriaValueMap.containsKey(id)){
+			return null;
+		}
+		return criteriaValueMap.get(id);
+	}
+	@Override
+	public Object getPartValue(String id) {
+		return partValueMap.get(id);
+	}
+	
+	@Override
+	public void storeCriteriaValue(String id, Object obj) {
+		criteriaValueMap.put(id, obj);
+	}
+	@Override
+	public void storePartValue(String id, Object obj) {
+		partValueMap.put(id, obj);
+	}
+	
+	@Override
+	public boolean partValueExist(String id) {
+		return partValueMap.containsKey(id);
+	}
+
+	public void clean() {
+		criteriaValueMap.clear();
+		partValueMap.clear();
+	}
 }