From 88579da9fef9b6d2af5a5c9d7d1ec3c7ae1d2ab5 Mon Sep 17 00:00:00 2001 From: Tuukka Lehtonen Date: Wed, 23 Dec 2020 14:57:10 +0200 Subject: [PATCH] Manually "cherry-picked" changes from ae2e31aa to release/1.35.2.1 The hope is this will at least help with OOM problems in long-living simupedia applications also with this older platform version. gitlab #594 Change-Id: Ic03dff331498fbf508ba8d2ccb6af3fbdfaf7913 (cherry picked from commit 7985cdde8fa4dfa211fc12b64c6a2561708da8f2) --- .../simantics/db/impl/query/CacheEntry.java | 1 + .../db/impl/query/CacheEntryBase.java | 25 ++++++ .../db/impl/query/QueryCollectorImpl.java | 1 + .../db/impl/query/QueryIdentityHash.java | 6 +- .../db/impl/query/QueryIdentityHashSet.java | 20 ++++- .../server/request/DocumentRequest.java | 81 ++++++++++--------- .../document/server/request/NodesRequest.java | 65 +++++++++------ 7 files changed, 132 insertions(+), 67 deletions(-) diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntry.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntry.java index d65622dad..9f4e5e3e4 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntry.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntry.java @@ -42,6 +42,7 @@ public abstract class CacheEntry { abstract T getResult(); abstract CacheEntry pruneFirstParents(); + abstract void pruneParentSet(); abstract void removeParent(CacheEntry entry); abstract void addParent(CacheEntry entry); abstract boolean hasParents(); diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntryBase.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntryBase.java index d30d59320..297f4738f 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntryBase.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntryBase.java @@ -258,6 +258,31 @@ abstract public class CacheEntryBase extends CacheEntry { } + + @Override + void pruneParentSet() { + // First parent is discarded => look for more parents + if(p2OrParents instanceof QueryIdentityHashSet) { + + QueryIdentityHashSet set = (QueryIdentityHashSet)p2OrParents; + set.removeDiscardedReally(); + if(set.isEmpty()) p2OrParents = null; + + } else if(p2OrParents instanceof CacheEntry) { + + CacheEntry entry = (CacheEntry)p2OrParents; + if(entry.isDiscarded()) { + // Second entry is also discarded => all empty + p2OrParents = null; + } + + } else { + + // Nothing left + + } + } + @Override final public void removeParent(CacheEntry entry) { diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java index 965f1e39f..1e6cc0214 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java @@ -144,6 +144,7 @@ class QueryCollectorImpl implements QueryProcessor.QueryCollector { } else { + entry.pruneParentSet(); support.setLevel(entry, parent.getLevel() + 1); } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHash.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHash.java index 4842cf5a6..396f1ba07 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHash.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHash.java @@ -226,7 +226,11 @@ abstract public class QueryIdentityHash extends THash { public Object getOriginalRequest() { throw new UnsupportedOperationException(); } - + + @Override + void pruneParentSet() { + } + }; /** diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHashSet.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHashSet.java index 3a7eb6182..ac2602fcb 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHashSet.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHashSet.java @@ -147,7 +147,25 @@ final public class QueryIdentityHashSet extends QueryIdentityHash implements Ite } } - + + final public void removeDiscardedReally() { + + tempDisableAutoCompaction(); + try { + + for(int i=0;i<_set.length;i++) { + CacheEntry entry = _set[i]; + if(entry != null && REMOVED != entry) { + if(entry.isDiscarded()) removeAt(i); + } + } + + } finally { + reenableAutoCompaction(false); + } + + } + /** * Creates an iterator over the values of the set. The iterator * supports element deletion. diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/DocumentRequest.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/DocumentRequest.java index 9a53060be..be5570f7f 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/DocumentRequest.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/DocumentRequest.java @@ -1,6 +1,7 @@ package org.simantics.document.server.request; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; @@ -9,64 +10,64 @@ import java.util.Set; import org.simantics.db.ReadGraph; import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; +import org.simantics.db.common.request.UnaryRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.VariableRead; import org.simantics.db.layer0.variable.Variable; import org.simantics.document.server.JSONObject; public class DocumentRequest extends VariableRead> { - - public static boolean PROFILE = false; - // Thresholds in microseconds - public static int PROFILE_THRESHOLD_NODEREQUEST = 2000; - public static int PROFILE_THRESHOLD_VALUEREQUEST = 500; + + public static boolean PROFILE = false; + // Thresholds in microseconds + public static int PROFILE_THRESHOLD_NODEREQUEST = 2000; + public static int PROFILE_THRESHOLD_VALUEREQUEST = 500; public DocumentRequest(Variable var) { super(var); - } + } + + static class CollectNodesRequest extends UnaryRead, Collection> { + + public CollectNodesRequest(Collection nodes) { + super(nodes); + } + + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { + HashSet rs = new HashSet<>(); // result + for(Variable node : parameter) { + rs.add(graph.syncRequest(new NodeRequest(node))); + } + return rs; + } + + } + + private static final Comparator JSON_COMPARATOR = (o1, o2) -> o1.id.compareTo(o2.id); + + @Override + public List perform(ReadGraph graph) throws DatabaseException { + + long s = System.nanoTime(); - @Override - public List perform(ReadGraph graph) throws DatabaseException { - - long s = System.nanoTime(); - Set nodes = graph.syncRequest(new NodesRequest(variable), TransientCacheAsyncListener.>instance()); - HashSet rs = new HashSet(); // result if(nodes.isEmpty()) { return Collections.emptyList(); } - - - /*TreeMap nodeMap = new TreeMap(); - - for (Variable node : nodes) { - nodeMap.put(node.getURI(graph), node); - } - System.out.println("*************************************************************************"); - for (Variable node : nodeMap.values()) { - System.out.println(" " + node.getURI(graph)); - }*/ - - for(Variable node : nodes) { - rs.add(graph.syncRequest(new NodeRequest(node), TransientCacheAsyncListener.instance())); - } - ArrayList result = new ArrayList(rs); - Collections.sort(result, new Comparator() { + Collection rs = graph.syncRequest(new CollectNodesRequest(nodes)); + + ArrayList result = new ArrayList<>(rs); + Collections.sort(result, JSON_COMPARATOR); - @Override - public int compare(JSONObject o1, JSONObject o2) { - return o1.id.compareTo(o2.id); - } - - }); - if(PROFILE) { - long dura = System.nanoTime()-s; - System.err.println("DocumentRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph)); + long dura = System.nanoTime()-s; + System.err.println("DocumentRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph)); } - return result; + return result; + + } - } } \ No newline at end of file diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/NodesRequest.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/NodesRequest.java index f3f1177fc..17666df6f 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/NodesRequest.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/NodesRequest.java @@ -1,12 +1,12 @@ package org.simantics.document.server.request; -import gnu.trove.set.hash.THashSet; - import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Set; import org.simantics.db.ReadGraph; +import org.simantics.db.common.request.UnaryRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.VariableChildren; import org.simantics.db.layer0.request.VariableRead; @@ -17,31 +17,46 @@ public class NodesRequest extends VariableRead> { public NodesRequest(Variable var) { super(var); - } - - @Override - public Set perform(ReadGraph graph) throws DatabaseException { - - long s = System.nanoTime(); - - StructuralResource2.getInstance(graph); - if(variable == null) - return Collections.emptySet(); - - Set nodes = new THashSet(); - Collection children = graph.syncRequest(new VariableChildren(variable)); - for(Variable child : children) { - Set childNodes = graph.syncRequest(new NodesRequest2(child)); - nodes.addAll(childNodes); - } - + } + + static class CollectNodesRequest2 extends UnaryRead, Set> { + + public CollectNodesRequest2(Collection nodes) { + super(nodes); + } + + @Override + public Set perform(ReadGraph graph) throws DatabaseException { + HashSet rs = new HashSet<>(); // result + for(Variable child : parameter) { + Set childNodes = graph.syncRequest(new NodesRequest2(child)); + rs.addAll(childNodes); + } + return rs; + } + + } + + @Override + public Set perform(ReadGraph graph) throws DatabaseException { + + long s = System.nanoTime(); + + StructuralResource2.getInstance(graph); + if(variable == null) + return Collections.emptySet(); + + Collection children = graph.syncRequest(new VariableChildren(variable)); + + Set nodes = graph.syncRequest(new CollectNodesRequest2(children)); + if(DocumentRequest.PROFILE) { - long dura = System.nanoTime()-s; - System.err.println("NodesRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph)); + long dura = System.nanoTime()-s; + System.err.println("NodesRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph)); } - - return nodes; - } + return nodes; + + } } \ No newline at end of file -- 2.47.1