From 1b962708cec68b2c253a4b368ff053d0f5033f30 Mon Sep 17 00:00:00 2001 From: villberg Date: Mon, 24 Nov 2014 10:47:16 +0000 Subject: [PATCH] (refs #5495) Performance optimizations for Project Game git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@30594 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../sysdyn/adapter/IndexVariable.java | 64 ++++++++++++++----- .../adapter/VariableValueSubscription.java | 12 +++- .../simantics/sysdyn/manager/GameResult.java | 9 +-- .../sysdyn/manager/OldSysdynExperiment.java | 41 +++++++++++- .../sysdyn/manager/SimulateDurationJob.java | 14 +++- .../sysdyn/manager/SysdynGameExperiment.java | 4 +- .../manager/SysdynGameExperimentInternal.java | 4 +- .../sysdyn/utils/DocumentationUtils.java | 11 ++-- 8 files changed, 128 insertions(+), 31 deletions(-) diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/IndexVariable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/IndexVariable.java index 4211a80a..6b4a6d7f 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/IndexVariable.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/IndexVariable.java @@ -25,6 +25,7 @@ import org.simantics.project.IProject; import org.simantics.simulation.experiment.IExperiment; import org.simantics.simulation.ontology.SimulationResource; import org.simantics.simulation.project.IExperimentManager; +import org.simantics.sysdyn.manager.OldSysdynExperiment; import org.simantics.sysdyn.manager.SysdynExperiment; import org.simantics.sysdyn.manager.SysdynModel; import org.simantics.sysdyn.manager.SysdynModelManager; @@ -47,7 +48,37 @@ public abstract class IndexVariable extends AbstractPropertyVariable { this.indexes = indexes; } - + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((indexes == null) ? 0 : indexes.hashCode()); + result = prime * result + ((parent == null) ? 0 : parent.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; + IndexVariable other = (IndexVariable) obj; + if (indexes == null) { + if (other.indexes != null) + return false; + } else if (!indexes.equals(other.indexes)) + return false; + if (parent == null) { + if (other.parent != null) + return false; + } else if (!parent.equals(other.parent)) + return false; + return true; + } + protected VariableSubscriptionManager getSubscriptionManager() { return this.experiment; } @@ -92,10 +123,9 @@ public abstract class IndexVariable extends AbstractPropertyVariable { * @author Teemu Lempinen * */ - class PropertyRequest extends ParametrizedPrimitiveRead { - + static class PropertyRequest extends ParametrizedPrimitiveRead { - public PropertyRequest(Variable indexVariable) { + public PropertyRequest(IndexVariable indexVariable) { super(indexVariable); } @@ -103,24 +133,21 @@ public abstract class IndexVariable extends AbstractPropertyVariable { @Override public void register(ReadGraph graph, Listener procedure) { - subscription = registerSubscription(this, procedure); + if(subscription != null) + System.err.println("err!"); + subscription = parameter.registerSubscription(this, procedure); } @Override public void unregistered() { if(subscription != null) { - unregisterSubscription(subscription); + parameter.unregisterSubscription(subscription); subscription = null; } } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object object) { - if(object instanceof IndexVariable.PropertyRequest && super.equals(object)) { - return this.parameter.equals(((PropertyRequest)object).parameter); - } else { - return super.equals(object); - } + + @Override + public String toString() { + return "PropertyRequest[" + parameter.rvi + "]"; } } @@ -308,5 +335,12 @@ public abstract class IndexVariable extends AbstractPropertyVariable { public Variable getParent(ReadGraph graph) throws DatabaseException { return parent; } + + public int getPublishCounter(ReadGraph graph) throws DatabaseException { + if(experiment instanceof OldSysdynExperiment) { + return ((OldSysdynExperiment)experiment).getPublishCounter(graph); + } + return 0; + } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java index 716fd588..a283e94c 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java @@ -23,15 +23,19 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.Listener; import org.simantics.db.request.ExternalRead; import org.simantics.db.service.QueryControl; +import org.simantics.utils.ObjectUtils; import org.simantics.utils.datastructures.Callback; public class VariableValueSubscription { public static final long SUBSCRIPTION_COLLECTION_INTERVAL = 2000L; + + private static final Object dummy = new Object(); protected ExternalRead request; protected IndexVariable variable; protected Listener listener; + protected Object lastFired = dummy; /** * To protect against invoking listener.exception multiple times which is @@ -52,15 +56,19 @@ public class VariableValueSubscription { public void update() { try { T value = variable.getValue(); - fireValue(value); + if(!ObjectUtils.objectEquals(value, lastFired)) { + fireValue(value); + lastFired = value; + } } catch (Throwable e) { fireException(e); } } void fireValue(T value) { - if (listener != null) + if (listener != null) { listener.execute(value); + } } void fireException(Throwable t) { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/GameResult.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/GameResult.java index 8997ca07..1beb980c 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/GameResult.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/GameResult.java @@ -1,7 +1,6 @@ package org.simantics.sysdyn.manager; import gnu.trove.list.array.TDoubleArrayList; -import gnu.trove.map.hash.THashMap; import org.simantics.modelica.data.DataSet; import org.simantics.modelica.data.SimulationResult; @@ -13,16 +12,18 @@ import org.simantics.modelica.data.SimulationResult; */ public class GameResult extends SimulationResult { - public GameResult(SysdynGameExperimentBase sysdynGameExperiment, THashMap results, String[] subscription) { + public GameResult(SysdynGameExperimentBase sysdynGameExperiment, TDoubleArrayList[] results, String[] subscription) { + + int timeIndex = sysdynGameExperiment.subscriptionIndexes.get("time"); // Get times - TDoubleArrayList timeList = results.get("time"); + TDoubleArrayList timeList = results[timeIndex]; double[] times = timeList.toArray(); String name; for(int k = 0; k < subscription.length; k++) { name = subscription[k]; - TDoubleArrayList valueList = results.get(name); + TDoubleArrayList valueList = results[k]; if(valueList.size() == timeList.size()) { this.variables.add(new DataSet(name, times, valueList.toArray())); } else { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/OldSysdynExperiment.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/OldSysdynExperiment.java index 8ebfb23f..f6e2d507 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/OldSysdynExperiment.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/OldSysdynExperiment.java @@ -34,11 +34,14 @@ import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.VirtualGraph; import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.ParametrizedPrimitiveRead; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.Logger; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.RuntimeDatabaseException; +import org.simantics.db.procedure.Listener; import org.simantics.db.request.Read; import org.simantics.db.service.VirtualGraphSupport; import org.simantics.layer0.Layer0; @@ -100,6 +103,42 @@ public class OldSysdynExperiment extends SysdynExperiment { public static OldSysdynExperiment getInstance() { return INSTANCE; } + + public class PublishExternalRead extends ParametrizedPrimitiveRead { + + private int value = 0; + private Listener listener = null; + + public PublishExternalRead(OldSysdynExperiment parameter) { + super(parameter); + } + + @Override + public void register(ReadGraph graph, Listener procedure) { + procedure.execute(value); + if(procedure.isDisposed()) return; + if(listener != null) throw new RuntimeDatabaseException("Internal error"); + listener = procedure; + } + + @Override + public void unregistered() { + listener = null; + } + + public void fire() { + value++; + if(listener != null) + listener.execute(value); + } + + } + + private PublishExternalRead publishRead = new PublishExternalRead(this); + + public int getPublishCounter(ReadGraph graph) throws DatabaseException { + return graph.syncRequest(publishRead); + } public SysdynResult getCurrentResult() { if(this.result == null) @@ -870,7 +909,7 @@ public class OldSysdynExperiment extends SysdynExperiment { */ @Override public void updateSubscriptions() { - if(!publishResults) return; + if(publishResults) publishRead.fire(); for(VariableValueSubscription subscription : getListenerSnapshot()) subscription.update(); skippedVariableUpdate = false; diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SimulateDurationJob.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SimulateDurationJob.java index f411138f..76238491 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SimulateDurationJob.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SimulateDurationJob.java @@ -6,6 +6,7 @@ import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.simantics.simulation.experiment.ExperimentState; import org.simantics.sysdyn.solver.ISolver; +import org.simantics.utils.logging.TimeLogger; class SimulateDurationJob extends Job { @@ -13,12 +14,14 @@ class SimulateDurationJob extends Job { private double duration; private final SysdynGameExperimentBase base; private final ISolver solver; + final private boolean asJob; - public SimulateDurationJob(SysdynGameExperimentBase base, String name, double duration) { + public SimulateDurationJob(SysdynGameExperimentBase base, String name, double duration, boolean asJob) { super(name); this.base = base; this.solver = base.getSolver(); this.duration = duration; + this.asJob = asJob; } @Override @@ -31,9 +34,12 @@ class SimulateDurationJob extends Job { if(base == null || base.getState() != ExperimentState.STOPPED) return Status.OK_STATUS; + TimeLogger.resetTime(); + long start = System.nanoTime(); - base.changeState(ExperimentState.RUNNING); + if(asJob) base.changeState(ExperimentState.RUNNING); + int nSteps = (int)(duration / base.stepLength); int work = 1 + nSteps * 3 + 2; // initialization + number of steps * number of phases per step + set result + call result listeners @@ -87,7 +93,7 @@ class SimulateDurationJob extends Job { base.resultsChanged(true); monitor.worked(1); - base.changeState(ExperimentState.STOPPED); + if(asJob) base.changeState(ExperimentState.STOPPED); } catch (Exception e) { e.printStackTrace(); @@ -97,6 +103,8 @@ class SimulateDurationJob extends Job { long end = System.nanoTime(); // System.err.println("simulate duration took " + 1e-6*(end-start) + "ms."); + TimeLogger.log("SimulateDuration"); + return Status.OK_STATUS; } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java index 6d8d4a92..53aec601 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java @@ -77,7 +77,7 @@ public class SysdynGameExperiment extends SysdynGameExperimentBase { if(control == null) control = new FMUControlJNI(); - results = new THashMap(); + results = new TDoubleArrayList[results.length]; } @@ -333,6 +333,8 @@ public class SysdynGameExperiment extends SysdynGameExperimentBase { for(int i = 0; i < subscription.length; i++) { subscriptionIndexes.put(subscription[i], i); } + + results = new TDoubleArrayList[subscription.length]; // Initialize container for current simulation results currentValues = new double[subscription.length]; diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperimentInternal.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperimentInternal.java index a0338fdc..23b17f63 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperimentInternal.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperimentInternal.java @@ -57,7 +57,7 @@ public class SysdynGameExperimentInternal extends SysdynGameExperimentBase { super.init(g); - results = new THashMap(); + results = null; solver = new InternalSolver(this, sysdynModel, true, new ISolverMonitor() { @@ -106,6 +106,8 @@ public class SysdynGameExperimentInternal extends SysdynGameExperimentBase { // Initialize container for current simulation results currentValues = new double[subscription.length]; + results = new TDoubleArrayList[currentValues.length]; + // subscribe all variables //solver.subscribe(subscription); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/DocumentationUtils.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/DocumentationUtils.java index b2c4b716..c82366cb 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/DocumentationUtils.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/DocumentationUtils.java @@ -22,6 +22,7 @@ import org.simantics.db.common.request.UniqueRead; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.ListUtils; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.exception.MissingVariableException; import org.simantics.db.layer0.util.EvaluatingListener; import org.simantics.db.layer0.util.EvaluatingListener.Criterion; import org.simantics.db.layer0.util.EvaluatingListener.Evaluation; @@ -631,8 +632,7 @@ public class DocumentationUtils { try { Pair nameAndIndices = splitToNameAndIndices(parameter2); org.simantics.db.layer0.variable.Variable v = parameter.browsePossible(graph, "/" + nameAndIndices.first + "#value#" + nameAndIndices.second); - //if(v == null) throw new MissingVariableException("No variable for SysDyn reference path: " + parameter2); - if(v == null) return null; + if(v == null) throw new MissingVariableException("No variable for SysDyn reference path: " + parameter2 + " from variable " + parameter.getURI(graph) ); return v; } catch (Throwable e) { throw new DatabaseException(e); @@ -651,10 +651,13 @@ public class DocumentationUtils { } - public static org.simantics.db.layer0.variable.Variable lastValueIndexed(ReadGraph graph, org.simantics.db.layer0.variable.Variable run, String path) throws DatabaseException { - if(run == null) return null; + + if(run == null) + throw new DatabaseException("Input variable (run) is null"); + return graph.syncRequest(new LastValueIndexed(run, path)); + } public static org.simantics.db.layer0.variable.Variable equation(ReadGraph graph, org.simantics.db.layer0.variable.Variable input, String path) throws DatabaseException { -- 2.47.1