From f4ee0c3759bc00541f5db67eae9e43ce760d3107 Mon Sep 17 00:00:00 2001 From: villberg Date: Mon, 27 Oct 2014 07:18:56 +0000 Subject: [PATCH] (refs #5441) Global model cache for speeding up deployed model initialization git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@30490 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../fi/semantum/sysdyn/solver/Assignment.java | 6 +- .../fi/semantum/sysdyn/solver/CodeCache.java | 60 +++++++++ .../semantum/sysdyn/solver/Environment.java | 10 ++ .../src/fi/semantum/sysdyn/solver/Model.java | 83 +++++++++++- .../sysdyn/solver/ParameterDeclaration.java | 2 +- .../src/fi/semantum/sysdyn/solver/Parser.java | 1 - .../src/fi/semantum/sysdyn/solver/Solver.java | 120 +++++------------- .../sysdyn/solver/VariableDeclaration.java | 2 +- 8 files changed, 182 insertions(+), 102 deletions(-) create mode 100644 fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/CodeCache.java diff --git a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Assignment.java b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Assignment.java index 67752379..2a49d408 100644 --- a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Assignment.java +++ b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Assignment.java @@ -18,7 +18,7 @@ public class Assignment { public Variable target; public IExpression[] subscripts; public IExpression expression; - public boolean assigned = false; + //public boolean assigned = false; public boolean isConstant = false; public Assignment(IFrame model, Variable target, IExpression[] subscripts, IExpression expression) { @@ -44,13 +44,13 @@ public class Assignment { } } - public void assign(IEnvironment env) { + public void assign(Environment env) { try { Object value = expression.evaluate(env); if(value != null) { validate(target, value); target.assign(env, subscripts, value); - assigned = true; + env.setAssigned(this); } } catch (ExecutionException e) { if(model instanceof Model) { diff --git a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/CodeCache.java b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/CodeCache.java new file mode 100644 index 00000000..f43cb99e --- /dev/null +++ b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/CodeCache.java @@ -0,0 +1,60 @@ +package fi.semantum.sysdyn.solver; + +import java.io.StringReader; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import fi.semantum.sysdyn.solver.Model.Globals; +import fi.semantum.sysdyn.solver.parser.ModelParser; +import fi.semantum.sysdyn.solver.parser.ParseException; +import fi.semantum.sysdyn.solver.parser.SimpleNode; + +public class CodeCache { + + final static int CACHE_SIZE = 5; + + private static CodeCache INSTANCE; + + final Map models = new HashMap(); + final LinkedList codes = new LinkedList(); + + public static CodeCache getInstance() { + if(INSTANCE == null) INSTANCE = new CodeCache(); + return INSTANCE; + } + + private CodeCache() { + } + + public Model getModel(String code) throws ParseException { + + Model model = models.get(code); + if(model == null) { + + StringReader reader = new StringReader(code); + ModelParser modelParser = new ModelParser(reader); + SimpleNode n = (SimpleNode)modelParser.stored_definition(); + + Parser parser = new Parser(); + model = new Model(new Globals(), "", false); + parser.walk(n, 0, model); + + model.prepare(); + model.prepareFunctions(); + model.sortAssignments(); + + models.put(code, model); + if(codes.size() == 5) { + String last = codes.removeLast(); + models.remove(last); + codes.addFirst(code); + } + + } + + return model; + + } + +} diff --git a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Environment.java b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Environment.java index 135410d7..247a93d1 100644 --- a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Environment.java +++ b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Environment.java @@ -734,4 +734,14 @@ final public class Environment implements IEnvironment, ISystem { put(index, value); } + public void setAssigned(Object ass) { + assigned.add(ass); + } + + public boolean isAssigned(Object o) { + return assigned.contains(o); + } + + private Set assigned = new HashSet(); + } diff --git a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Model.java b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Model.java index ab861d89..ff2527ff 100644 --- a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Model.java +++ b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Model.java @@ -12,11 +12,19 @@ package fi.semantum.sysdyn.solver; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; +import org.simantics.utils.datastructures.MapList; + +import fi.semantum.sysdyn.solver.IExpression.ExpressionVisitor; + class Model implements IFrame { static class Globals { @@ -41,9 +49,11 @@ class Model implements IFrame { public final Globals globals; public int line = -1; - public String name; public boolean isEnumClass; + private String name; + private int size; + public Model(Globals globals, String name, boolean isEnumClass) { this.globals = globals; this.name = name; @@ -333,24 +343,28 @@ class Model implements IFrame { if(!done) throw new IllegalStateException(); - int nextIndex = 0; + size = 0; for(Map.Entry entry : names.entrySet()) { VariableBase base = entry.getValue(); - base.index = nextIndex; + base.index = size; if(PRINT) System.err.println("Variable: " + entry.getKey() + " " + base.index + " " + Arrays.toString(base.dimensions)); int dim = base.dimension(); if(dim == -1) dim = 1; - nextIndex += dim; + size += dim; } if(PRINT) System.err.println("=================="); - return nextIndex; + return size; } + public int getSize() { + return size; + } + public void prettyPrint() { System.err.println("initials"); @@ -441,4 +455,63 @@ class Model implements IFrame { } + public void prepareFunctions() { + + for(Fn fn : functions.values()) { + if(fn instanceof Function) + ((Function)fn).prepare(); + } + + } + + public void sortAssignments() { + + final MapList asses = new MapList(); + for(Assignment ass : assignments) asses.add(ass.target.base.name, ass); + + final List found = new ArrayList(); + final Set visited = new HashSet(); + + ExpressionVisitor sortVisitor = new ExpressionVisitor() { + @Override + public void visit(IExpression expression) { + if(expression instanceof Variable) { + Variable var = (Variable)expression; + if(visited.add(var.base.name)) { + for(Assignment ass : asses.getValues(var.base.name)) { + ass.expression.accept(this); + if(ass.subscripts != null) + for(IExpression e : ass.subscripts) e.accept(this); + } + found.add(var.base); + } + } + } + }; + + // Sort assignments + for(Assignment ass : assignments) { + ass.target.accept(sortVisitor); + } + + Collections.sort(assignments, new Comparator() { + + @Override + public int compare(Assignment o1, Assignment o2) { + int i1 = found.indexOf(o1.target.base); + int i2 = found.indexOf(o2.target.base); + if(i1 < i2) return -1; + else if (i1 > i2) return 1; + return 0; + } + + + }); + + assignmentArray = assignments.toArray(new Assignment[assignments.size()]); + derivativeArray = derivatives.toArray(new Assignment[derivatives.size()]); + parameterArray = parameters.toArray(new ParameterDeclaration[parameters.size()]); + + } + } \ No newline at end of file diff --git a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/ParameterDeclaration.java b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/ParameterDeclaration.java index 72cbab5e..45ec0f0b 100644 --- a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/ParameterDeclaration.java +++ b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/ParameterDeclaration.java @@ -17,7 +17,7 @@ public class ParameterDeclaration implements IExpression { public Variable variable; public IExpression modification; - public boolean assigned = false; +// public boolean assigned = false; public ParameterDeclaration(Variable variable, IExpression modification) { this.variable = variable; diff --git a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Parser.java b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Parser.java index 32695d74..3fe43ba4 100644 --- a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Parser.java +++ b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Parser.java @@ -365,7 +365,6 @@ public class Parser { SimpleNode child = (SimpleNode)n.jjtGetChild(0); String packagePath = getPackagePath(child); String functionName = packagePath + child.op; - System.err.println("function " + functionName + " at line " + child.line); ArrayList stms2 = new ArrayList(); Function function = new Function(functionName, new StatementList(stms2), child.line); ArrayList composition = (ArrayList)walk(child, indent+2, function); diff --git a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Solver.java b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Solver.java index 80484a56..d33e12cc 100644 --- a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Solver.java +++ b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Solver.java @@ -11,19 +11,8 @@ *******************************************************************************/ package fi.semantum.sysdyn.solver; -import java.io.StringReader; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import org.simantics.utils.datastructures.MapList; - -import fi.semantum.sysdyn.solver.IExpression.ExpressionVisitor; -import fi.semantum.sysdyn.solver.Model.Globals; -import fi.semantum.sysdyn.solver.parser.ModelParser; import fi.semantum.sysdyn.solver.parser.SimpleNode; public class Solver { @@ -62,52 +51,6 @@ public class Solver { ready = false; } - private void sortAssignments() { - - final MapList asses = new MapList(); - for(Assignment ass : model.assignments) asses.add(ass.target.base.name, ass); - - final List found = new ArrayList(); - final Set visited = new HashSet(); - - ExpressionVisitor sortVisitor = new ExpressionVisitor() { - @Override - public void visit(IExpression expression) { - if(expression instanceof Variable) { - Variable var = (Variable)expression; - if(visited.add(var.base.name)) { - for(Assignment ass : asses.getValues(var.base.name)) { - ass.expression.accept(this); - if(ass.subscripts != null) - for(IExpression e : ass.subscripts) e.accept(this); - } - found.add(var.base); - } - } - } - }; - - // Sort assignments - for(Assignment ass : model.assignments) { - ass.target.accept(sortVisitor); - } - - Collections.sort(model.assignments, new Comparator() { - - @Override - public int compare(Assignment o1, Assignment o2) { - int i1 = found.indexOf(o1.target.base); - int i2 = found.indexOf(o2.target.base); - if(i1 < i2) return -1; - else if (i1 > i2) return 1; - return 0; - } - - - }); - - } - private SimpleNode n; private String codeCache = null; @@ -133,37 +76,32 @@ public class Solver { long startNanos = System.nanoTime(); - if(!input.equals(codeCache)) { + model = CodeCache.getInstance().getModel(input); - StringReader reader = new StringReader(input); - ModelParser modelParser = new ModelParser(reader); - n = (SimpleNode)modelParser.stored_definition(); +// if(!input.equals(codeCache)) { +// +// StringReader reader = new StringReader(input); +// ModelParser modelParser = new ModelParser(reader); +// n = (SimpleNode)modelParser.stored_definition(); +// +// Parser parser = new Parser(); +// model = new Model(new Globals(), "", false); +// parser.walk(n, 0, model); +// +// model.prepare(); +// model.prepareFunctions(); +// model.sortAssignments(); +// +// codeCache = input; +// +// } - } - - Parser parser = new Parser(); - model = new Model(new Globals(), "", false); - parser.walk(n, 0, model); - codeCache = input; - - env = new Environment(model, defaultStep, start); + int size = model.getSize(); - int size = model.prepare(); + env = new Environment(model, defaultStep, start); env.setSize(size); - - for(Fn fn : model.functions.values()) { - if(fn instanceof Function) - ((Function)fn).prepare(); - } - env.valueTable = new Object[size+STACK_SIZE]; - sortAssignments(); - - model.assignmentArray = model.assignments.toArray(new Assignment[model.assignments.size()]); - model.derivativeArray = model.derivatives.toArray(new Assignment[model.derivatives.size()]); - model.parameterArray = model.parameters.toArray(new ParameterDeclaration[model.parameters.size()]); - newValues = new Object[Math.max(model.assignments.size(),model.derivatives.size())]; int condition = 1; @@ -171,6 +109,10 @@ public class Solver { StringBuilder errors = null; + ArrayList assignments = new ArrayList(); + assignments.addAll(model.assignments); + assignments.addAll(model.initials); + while(condition > 0 && loops++ < MAX_LOOPS) { if(loops == MAX_LOOPS) errors = new StringBuilder(); @@ -183,11 +125,11 @@ public class Solver { for(ParameterDeclaration pd : model.parameters) { try { - if(!pd.assigned) { + if(!env.isAssigned(pd)) { Object value = pd.modification.evaluate(env); validate(pd.variable, value); pd.variable.assign(env, null, value); - pd.assigned = true; + env.setAssigned(pd); } } catch (Exception e) { String error = " -" + pd.variable.toString() + ": " + e.getMessage(); @@ -203,13 +145,9 @@ public class Solver { } } - ArrayList assignments = new ArrayList(); - assignments.addAll(model.assignments); - assignments.addAll(model.initials); - for(VariableDeclaration vd : model.variables) { try { - if(!vd.assigned) { + if(!env.isAssigned(vd)) { for(Argument arg : vd.modification.args) { if(arg.name.endsWith("start")) { Object value = arg.modification.evaluate(env); @@ -233,7 +171,7 @@ public class Solver { // efficient way for (Assignment a : assignments) { if (vd.variable.base.equals(a.target.base)) { - a.assigned = true; + env.setAssigned(a); } } } @@ -255,7 +193,7 @@ public class Solver { for(Assignment ass : assignments) { try { - if(!ass.assigned) + if(!env.isAssigned(ass)) ass.assign(env); } catch (Exception e) { String error = " -" + ass.target.toString() + ": " + e.getMessage(); diff --git a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/VariableDeclaration.java b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/VariableDeclaration.java index 83958d39..eb92bfa5 100644 --- a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/VariableDeclaration.java +++ b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/VariableDeclaration.java @@ -19,7 +19,7 @@ public class VariableDeclaration implements IExpression { public String direction; public String type; public ArgumentList modification; - public boolean assigned = false; +// public boolean assigned = false; public VariableDeclaration(Variable variable, String direction, String type, ArgumentList modification) { this.variable = variable; -- 2.47.1