The cached hashcode is calculated before inserting the cached hash value
in the TransferableGraph1.extensions TreeMap. Reading and inspection
must be done with this in mind.
This cached value is used to optimize platform startup by removing the
need to calculate the TransferableGraph1 structure hashcode at runtime
which can be quite expensive because the standard databoard Bindings are
slow compared to optimal methods. Of course an optimized binding could
be used to speed the calculation up dramatically but it still can't beat
caching the final (immutable) hashCode value.
refs #7806
Change-Id: I9d4fc6549cba567f95b19f80bd15c1ccfbbedf07
import org.simantics.databoard.Bindings;
import org.simantics.databoard.Files;
import org.simantics.databoard.adapter.AdaptException;
import org.simantics.databoard.Bindings;
import org.simantics.databoard.Files;
import org.simantics.databoard.adapter.AdaptException;
+import org.simantics.databoard.binding.Binding;
import org.simantics.databoard.binding.error.BindingException;
import org.simantics.databoard.binding.error.BindingException;
-import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
import org.simantics.databoard.binding.mutable.Variant;
import org.simantics.databoard.container.DataContainer;
import org.simantics.databoard.container.DataContainers;
import org.simantics.databoard.binding.mutable.Variant;
import org.simantics.databoard.container.DataContainer;
import org.simantics.databoard.container.DataContainers;
-import org.simantics.databoard.serialization.SerializationException;
import org.simantics.graph.compiler.internal.parsing.Parsing;
import org.simantics.graph.compiler.internal.procedures.AddConsistsOf;
import org.simantics.graph.compiler.internal.procedures.ApplyTemplates;
import org.simantics.graph.compiler.internal.parsing.Parsing;
import org.simantics.graph.compiler.internal.procedures.AddConsistsOf;
import org.simantics.graph.compiler.internal.procedures.ApplyTemplates;
import org.simantics.graph.query.CompositeGraph;
import org.simantics.graph.query.Paths;
import org.simantics.graph.query.TransferableGraphConversion;
import org.simantics.graph.query.CompositeGraph;
import org.simantics.graph.query.Paths;
import org.simantics.graph.query.TransferableGraphConversion;
+import org.simantics.graph.representation.Extensions;
import org.simantics.graph.representation.TransferableGraph1;
import org.simantics.graph.store.GraphStore;
import org.simantics.ltk.FileSource;
import org.simantics.graph.representation.TransferableGraph1;
import org.simantics.graph.store.GraphStore;
import org.simantics.ltk.FileSource;
}
public static InputStream write(TransferableGraph1 tg) throws BindingException, IOException {
}
public static InputStream write(TransferableGraph1 tg) throws BindingException, IOException {
- byte[] buffer = DataContainers.writeFile(
- new DataContainer("graph", 1, new Variant(TransferableGraph1.BINDING, tg))
- );
- return new ByteArrayInputStream(buffer);
+ Binding binding = TransferableGraph1.BINDING;
+ int hashCode = binding.hashValue(tg);
+ tg.extensions.put(Extensions.CACHED_HASHCODE, new Variant(Bindings.INTEGER, hashCode));
+ try {
+ byte[] buffer = DataContainers.writeFile(
+ new DataContainer("graph", 1, new Variant(TransferableGraph1.BINDING, tg))
+ );
+ return new ByteArrayInputStream(buffer);
+ } finally {
+ tg.extensions.remove(Extensions.CACHED_HASHCODE);
+ }
}
public static CompilationResult compile(
}
public static CompilationResult compile(
public static void reportTime(String taskName, long beginTime, long endTime) {
StringBuilder sb = new StringBuilder();
public static void reportTime(String taskName, long beginTime, long endTime) {
StringBuilder sb = new StringBuilder();
- Formatter formatter = new Formatter(sb, Locale.US);
- formatter.format("%-25s %8.4f ms", taskName, (endTime - beginTime)*1e-6);
-
+ @SuppressWarnings("resource")
+ Formatter formatter = new Formatter(sb, Locale.US);
+ formatter.format("%-25s %8.4f ms", taskName, (endTime - beginTime)*1e-6);
+
out.println(sb.toString());
}
out.println(sb.toString());
}
import java.util.TreeMap;
import java.util.TreeMap;
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
import org.simantics.databoard.binding.mutable.Variant;
public class Extensions {
import org.simantics.databoard.binding.mutable.Variant;
public class Extensions {
+
+ public static final Binding BINDING = Bindings.getBindingUnchecked(Extensions.class);
+
+ /**
+ * Used for storing a cached hash code computed from a
+ * {@link TransferableGraph1} instance <em>without</em> this cached hashcode
+ * key,value pair in the <code>extensions</code> map.
+ */
+ public final static String CACHED_HASHCODE = "cached.hashCode";
+
final public static String CLUSTERING = "clustering";
final public static String CLUSTER_SETS = "clusterSets";
final public static int NO_CLUSTER_SET = -1;
final public static int ROOT_LIBRARY_CLUSTER_SET = -1;
final public static int INDEX_ROOT_CLUSTER_SET = -2;
final public static String CLUSTERING = "clustering";
final public static String CLUSTER_SETS = "clusterSets";
final public static int NO_CLUSTER_SET = -1;
final public static int ROOT_LIBRARY_CLUSTER_SET = -1;
final public static int INDEX_ROOT_CLUSTER_SET = -2;
-
- public TreeMap<String, Variant> map = new TreeMap<String, Variant>();
-
+
+ public TreeMap<String, Variant> map;
+
+ public Extensions() {
+ this.map = new TreeMap<>();
+ }
+
public Extensions(TreeMap<String, Variant> map) {
this.map = map;
}
public Extensions(TreeMap<String, Variant> map) {
this.map = map;
}