Improvements to JaCObs Jackson serializer/deserializer
- deserialization of channel proxies is now using public Jackson APIs only.
- Channel garbage collection implemented.
- HashSets replaced by LinkedHashSets in order to make the serialized form more deterministic.
diff --git a/src/main/java/org/apache/ode/jacob/CompositeProcess.java b/src/main/java/org/apache/ode/jacob/CompositeProcess.java
index c1e5843..785fed0 100644
--- a/src/main/java/org/apache/ode/jacob/CompositeProcess.java
+++ b/src/main/java/org/apache/ode/jacob/CompositeProcess.java
@@ -20,13 +20,13 @@
import java.lang.reflect.Method;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.Set;
@SuppressWarnings("serial")
public final class CompositeProcess extends ChannelListener {
- private Set<ChannelListener> processes = new HashSet<ChannelListener>();
+ private Set<ChannelListener> processes = new LinkedHashSet<ChannelListener>();
public CompositeProcess() {
}
diff --git a/src/main/java/org/apache/ode/jacob/ReceiveProcess.java b/src/main/java/org/apache/ode/jacob/ReceiveProcess.java
index eccfd09..70f9191 100644
--- a/src/main/java/org/apache/ode/jacob/ReceiveProcess.java
+++ b/src/main/java/org/apache/ode/jacob/ReceiveProcess.java
@@ -20,7 +20,7 @@
import java.lang.reflect.Method;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.Set;
@@ -53,7 +53,7 @@
public Set<Method> getImplementedMethods() {
if (_implementedMethods == null) {
- Set<Method> implementedMethods = new HashSet<Method>();
+ Set<Method> implementedMethods = new LinkedHashSet<Method>();
ClassUtil.getImplementedMethods(implementedMethods, receiver.getClass());
_implementedMethods = Collections.unmodifiableSet(implementedMethods);
}
diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/ChannelProxySerializer.java b/src/main/java/org/apache/ode/jacob/soup/jackson/ChannelProxySerializer.java
index 0817461..a3cee06 100644
--- a/src/main/java/org/apache/ode/jacob/soup/jackson/ChannelProxySerializer.java
+++ b/src/main/java/org/apache/ode/jacob/soup/jackson/ChannelProxySerializer.java
@@ -19,6 +19,8 @@
package org.apache.ode.jacob.soup.jackson;
import java.io.IOException;
+import java.util.LinkedHashSet;
+import java.util.Set;
import org.apache.ode.jacob.Channel;
import org.apache.ode.jacob.ChannelProxy;
@@ -34,6 +36,8 @@
public class ChannelProxySerializer extends StdSerializer<ChannelProxy>{
+ private final Set<Integer> serializedChannels = new LinkedHashSet<Integer>();
+
protected ChannelProxySerializer() {
super(ChannelProxy.class);
}
@@ -61,8 +65,16 @@
SerializerProvider provider) throws JsonGenerationException, IOException {
CommChannel commChannel = (CommChannel) ChannelFactory.getBackend((Channel)value);
ClassNameIdResolver idResolver = new ClassNameIdResolver(provider.constructType(commChannel.getType()), provider.getTypeFactory());
+ Integer cid = (Integer)commChannel.getId();
jgen.writeStringField("channelType", idResolver.idFromBaseType());
- jgen.writeNumberField("channelId", (Integer)commChannel.getId());
+ jgen.writeNumberField("channelId", cid);
+
+ // save channel id for garbage collection
+ serializedChannels.add(cid);
+ }
+
+ public Set<Integer> getSerializedChannels() {
+ return serializedChannels;
}
}
diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/ContinuationValueInstantiator.java b/src/main/java/org/apache/ode/jacob/soup/jackson/ContinuationValueInstantiator.java
deleted file mode 100644
index d770ad1..0000000
--- a/src/main/java/org/apache/ode/jacob/soup/jackson/ContinuationValueInstantiator.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.ode.jacob.soup.jackson;
-
-import java.lang.reflect.Method;
-
-import org.apache.ode.jacob.JacobObject;
-import org.apache.ode.jacob.soup.Continuation;
-
-import com.fasterxml.jackson.databind.DeserializationConfig;
-import com.fasterxml.jackson.databind.deser.CreatorProperty;
-import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
-import com.fasterxml.jackson.databind.deser.ValueInstantiator;
-
-public class ContinuationValueInstantiator extends ValueInstantiator {
-
- @Override
- public String getValueTypeDesc() {
- return Continuation.class.getName();
- }
-
- @Override
- public boolean canCreateFromObjectWith() {
- return true;
- }
-
- @Override
- public SettableBeanProperty[] getFromObjectArguments(
- DeserializationConfig config) {
- return new CreatorProperty[] {
- new CreatorProperty("_closure", config.constructType(JacobObject.class), null, null, null, 0, null),
- new CreatorProperty("_method", config.constructType(Method.class), null, null, null, 1, null),
- new CreatorProperty("_args", config.constructType(Object[].class), null, null, null, 2, null)};
-
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/JacksonExecutionQueueImpl.java b/src/main/java/org/apache/ode/jacob/soup/jackson/JacksonExecutionQueueImpl.java
index e0892df..fb08f10 100644
--- a/src/main/java/org/apache/ode/jacob/soup/jackson/JacksonExecutionQueueImpl.java
+++ b/src/main/java/org/apache/ode/jacob/soup/jackson/JacksonExecutionQueueImpl.java
@@ -19,14 +19,19 @@
package org.apache.ode.jacob.soup.jackson;
import java.io.IOException;
+import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
import org.apache.ode.jacob.Channel;
import org.apache.ode.jacob.ChannelProxy;
import org.apache.ode.jacob.soup.Continuation;
import org.apache.ode.jacob.vpu.ExecutionQueueImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
@@ -35,11 +40,16 @@
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.BeanDescription;
+import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
@@ -51,20 +61,40 @@
*/
public class JacksonExecutionQueueImpl extends ExecutionQueueImpl {
+ private static final Logger LOG = LoggerFactory.getLogger(JacksonExecutionQueueImpl.class);
+
public JacksonExecutionQueueImpl() {
super(null);
}
public static void configureMapper(ObjectMapper om) {
- SimpleModule sm = new SimpleModule("jacobmodule");
- sm.addSerializer(ChannelProxy.class, new ChannelProxySerializer());
+ SimpleModule sm = new SimpleModule("jacob", Version.unknownVersion());
+
+ final ChannelProxySerializer cps = new ChannelProxySerializer();
+
+ sm.addSerializer(ChannelProxy.class, cps);
sm.addSerializer(Continuation.class, new ContinuationSerializer());
- sm.addSerializer(JacksonExecutionQueueImpl.class, new ExecutionQueueImplSerializer());
+ sm.addSerializer(JacksonExecutionQueueImpl.class, new ExecutionQueueImplSerializer(cps));
sm.addDeserializer(JacksonExecutionQueueImpl.class, new ExecutionQueueImplDeserializer());
sm.addDeserializer(Continuation.class, new ContinuationDeserializer());
sm.addDeserializer(Channel.class, new ChannelProxyDeserializer());
+ sm.setDeserializerModifier(new BeanDeserializerModifier() {
+
+ public JsonDeserializer<?> modifyDeserializer(
+ DeserializationConfig config, BeanDescription beanDesc,
+ JsonDeserializer<?> deserializer) {
+
+ // use channel proxy deserializer for channels.
+ if (Channel.class.isAssignableFrom(beanDesc.getBeanClass()) && beanDesc.getBeanClass().isInterface()) {
+ return new ChannelProxyDeserializer();
+ }
+
+ return super.modifyDeserializer(config, beanDesc, deserializer);
+ }
+ });
+
om.registerModule(sm);
om.disable(MapperFeature.AUTO_DETECT_CREATORS);
om.disable(MapperFeature.AUTO_DETECT_GETTERS);
@@ -82,8 +112,11 @@
public static class ExecutionQueueImplSerializer extends StdSerializer<JacksonExecutionQueueImpl> {
- public ExecutionQueueImplSerializer() {
+ private ChannelProxySerializer channelProxySerializer;
+
+ public ExecutionQueueImplSerializer(ChannelProxySerializer cps) {
super(JacksonExecutionQueueImpl.class);
+ this.channelProxySerializer = cps;
}
@Override
@@ -108,11 +141,44 @@
private void serializeContents(JacksonExecutionQueueImpl value, JsonGenerator jgen,
SerializerProvider provider) throws JsonGenerationException, IOException {
- jgen.writeNumberField("objIdCounter", value._objIdCounter);
+ channelProxySerializer.getSerializedChannels().clear();
+
+ // write metadata
+ jgen.writeNumberField("objIdCounter", value._objIdCounter);
jgen.writeNumberField("currentCycle", value._currentCycle);
+ // write continuations
jgen.writeObjectField("continuations", value._reactions.toArray(new Continuation[] {}));
+
+
+ // channel garbage collection
+ // - traverse whole object graph and record referenced channel proxies.
+ // - first, regularily serialize continuations.
+ // - second, serialize channels to a null serializer in order to record channel references
+ // without writing them to the stream.
+ // - remove unused channels.
+ // - serialize remaining channels.
+
+ // write channels to null serializer
+ JsonGenerator nullgen = new NullJsonGenerator(null, 0, jgen.getCodec());
+ nullgen.writeObjectField("channels", value._channels.values().toArray(new ChannelFrame[] {}));
+
+ // remove unreferenced channels (and keep those which have been exported using export()).
+ Set<Integer> referencedChannels = channelProxySerializer.getSerializedChannels();
+ for (Iterator<ChannelFrame> i = value._channels.values().iterator(); i.hasNext();) {
+ ChannelFrame cframe = i.next();
+ if (referencedChannels.contains(cframe.getId()) || cframe.getRefCount() > 0) {
+ // skip
+ } else {
+ LOG.debug("GC Channel: {}", cframe);
+ i.remove();
+ }
+ }
+
+ // write channels
jgen.writeObjectField("channels", value._channels.values().toArray(new ChannelFrame[] {}));
+
+ // write global data
jgen.writeObjectField("global", value._gdata);
}
}
@@ -152,13 +218,12 @@
for (ChannelFrame f : frames) {
soup._channels.put(f.getId(), f);
}
+ } else if ("global".equals(fieldname)) {
+ soup._gdata = jp.readValueAs(Serializable.class);
}
}
- // Garbage collection
- // TODO
-
return soup;
}
diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/JacobJacksonAnnotationIntrospector.java b/src/main/java/org/apache/ode/jacob/soup/jackson/JacobJacksonAnnotationIntrospector.java
index 0cb3a73..ba8b7b1 100644
--- a/src/main/java/org/apache/ode/jacob/soup/jackson/JacobJacksonAnnotationIntrospector.java
+++ b/src/main/java/org/apache/ode/jacob/soup/jackson/JacobJacksonAnnotationIntrospector.java
@@ -15,5 +15,5 @@
public ObjectIdInfo findObjectIdInfo(Annotated ann) {
return new ObjectIdInfo("@id", Object.class, ObjectIdGenerators.IntSequenceGenerator.class);
}
-
+
}
diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/JacobTypeResolverBuilder.java b/src/main/java/org/apache/ode/jacob/soup/jackson/JacobTypeResolverBuilder.java
index b477fcd..8a14a71 100644
--- a/src/main/java/org/apache/ode/jacob/soup/jackson/JacobTypeResolverBuilder.java
+++ b/src/main/java/org/apache/ode/jacob/soup/jackson/JacobTypeResolverBuilder.java
@@ -40,7 +40,6 @@
import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase;
import com.fasterxml.jackson.databind.type.TypeFactory;
-import com.fasterxml.jackson.databind.util.ClassUtil;
public class JacobTypeResolverBuilder extends StdTypeResolverBuilder {
@@ -65,7 +64,15 @@
return useForType(baseType) ? super.buildTypeSerializer(config, baseType, subtypes) : null;
}
+
+ @Override
+ public TypeDeserializer buildTypeDeserializer(DeserializationConfig config,
+ JavaType baseType, Collection<NamedType> subtypes) {
+
+ return (useForType(baseType)) ? super.buildTypeDeserializer(config, baseType, subtypes) : null;
+ }
+
private boolean useForType(JavaType t) {
if (JacobObject.class.isAssignableFrom(t.getRawClass())) {
return true;
@@ -82,18 +89,6 @@
return false;
}
- @Override
- public TypeDeserializer buildTypeDeserializer(DeserializationConfig config,
- JavaType baseType, Collection<NamedType> subtypes) {
-
- if (useForType(baseType)) {
- // set Channel as the default impl.
- defaultImpl(Channel.class);
- return super.buildTypeDeserializer(config, baseType, subtypes);
- }
-
- return null;
- }
public static class ChannelAwareTypeIdResolver extends TypeIdResolverBase {
@@ -119,18 +114,7 @@
}
public JavaType typeFromId(String id) {
- try {
- Class<?> cls = ClassUtil.findClass(id);
- if (Channel.class.isAssignableFrom(cls) && cls.isInterface()) {
- // return null to force Jackson to use default deserializer (which is the ChannelProxyDeserializer)
- return null;
- }
- return _typeFactory.constructSpecializedType(_baseType, cls);
- } catch (ClassNotFoundException e) {
- throw new IllegalArgumentException("Invalid type id '"+id+"' (for id type 'Id.class'): no such class found");
- } catch (Exception e) {
- throw new IllegalArgumentException("Invalid type id '"+id+"' (for id type 'Id.class'): "+e.getMessage(), e);
- }
+ return delegate.typeFromId(id);
}
public Id getMechanism() {
diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/NullJsonGenerator.java b/src/main/java/org/apache/ode/jacob/soup/jackson/NullJsonGenerator.java
new file mode 100644
index 0000000..08cd96a
--- /dev/null
+++ b/src/main/java/org/apache/ode/jacob/soup/jackson/NullJsonGenerator.java
@@ -0,0 +1,118 @@
+package org.apache.ode.jacob.soup.jackson;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import com.fasterxml.jackson.core.Base64Variant;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.ObjectCodec;
+import com.fasterxml.jackson.core.io.IOContext;
+import com.fasterxml.jackson.core.json.JsonGeneratorImpl;
+
+/**
+ * No-op Json generator.
+ *
+ * @author vanto
+ *
+ */
+public class NullJsonGenerator extends JsonGeneratorImpl {
+
+ public NullJsonGenerator(IOContext ctxt, int features, ObjectCodec codec) {
+ super(ctxt, features, codec);
+ }
+
+ public void flush() throws IOException {
+ }
+
+ protected void _releaseBuffers() {
+ }
+
+ protected void _verifyValueWrite(String typeMsg) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeStartArray() throws IOException, JsonGenerationException {
+ }
+
+ public void writeEndArray() throws IOException, JsonGenerationException {
+ }
+
+ public void writeStartObject() throws IOException, JsonGenerationException {
+ }
+
+ public void writeEndObject() throws IOException, JsonGenerationException {
+ }
+
+ public void writeFieldName(String name) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeString(String text) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeString(char[] text, int offset, int len)
+ throws IOException, JsonGenerationException {
+ }
+
+ public void writeRawUTF8String(byte[] text, int offset, int length)
+ throws IOException, JsonGenerationException {
+ }
+
+ public void writeUTF8String(byte[] text, int offset, int length)
+ throws IOException, JsonGenerationException {
+ }
+
+ public void writeRaw(String text) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeRaw(String text, int offset, int len) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeRaw(char[] text, int offset, int len) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeRaw(char c) throws IOException, JsonGenerationException {
+ }
+
+ public void writeBinary(Base64Variant b64variant, byte[] data, int offset,
+ int len) throws IOException, JsonGenerationException {
+ }
+
+ public void writeNumber(int v) throws IOException, JsonGenerationException {
+ }
+
+ public void writeNumber(long v) throws IOException, JsonGenerationException {
+ }
+
+ public void writeNumber(BigInteger v) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeNumber(double d) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeNumber(float f) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeNumber(BigDecimal dec) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeNumber(String encodedValue) throws IOException,
+ JsonGenerationException, UnsupportedOperationException {
+ }
+
+ public void writeBoolean(boolean state) throws IOException,
+ JsonGenerationException {
+ }
+
+ public void writeNull() throws IOException, JsonGenerationException {
+ }
+}
diff --git a/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java b/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java
index fff2ae1..a6c0837 100644
--- a/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java
+++ b/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java
@@ -30,9 +30,10 @@
import java.io.PrintStream;
import java.io.Serializable;
import java.lang.reflect.Method;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
@@ -80,9 +81,9 @@
* forward progress; this scenario would occur if a maximum processign
* time-per-instance policy were in effect.
*/
- protected Set<Continuation> _reactions = new HashSet<Continuation>();
+ protected Set<Continuation> _reactions = new LinkedHashSet<Continuation>();
- protected Map<Integer, ChannelFrame> _channels = new HashMap<Integer, ChannelFrame>();
+ protected Map<Integer, ChannelFrame> _channels = new LinkedHashMap<Integer, ChannelFrame>();
/**
* The "expected" cycle counter, use to detect database serialization
@@ -96,7 +97,7 @@
protected Serializable _gdata;
- private Map<Object, LinkedList<IndexedObject>> _index = new HashMap<Object, LinkedList<IndexedObject>>();
+ private Map<Object, LinkedList<IndexedObject>> _index = new LinkedHashMap<Object, LinkedList<IndexedObject>>();
public ExecutionQueueImpl(ClassLoader classLoader) {
_classLoader = classLoader;
@@ -454,9 +455,9 @@
boolean replicatedRecv;
- Set<ObjectFrame> objFrames = new HashSet<ObjectFrame>();
+ Set<ObjectFrame> objFrames = new LinkedHashSet<ObjectFrame>();
- Set<MessageFrame> msgFrames = new HashSet<MessageFrame>();
+ Set<MessageFrame> msgFrames = new LinkedHashSet<MessageFrame>();
public String description;
@@ -473,6 +474,18 @@
public Integer getId() {
return Integer.valueOf(id);
}
+
+ public int getRefCount() {
+ return refCount;
+ }
+
+ public Set<ObjectFrame> getObjFrames() {
+ return objFrames;
+ }
+
+ public Set<MessageFrame> getMsgFrames() {
+ return msgFrames;
+ }
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
type = (Class<?>)in.readObject();
@@ -535,7 +548,7 @@
@SuppressWarnings("serial")
protected static class CommGroupFrame implements Serializable {
boolean replicated;
- public Set<CommFrame> commFrames = new HashSet<CommFrame>();
+ public Set<CommFrame> commFrames = new LinkedHashSet<CommFrame>();
// default constructor for deserialization
public CommGroupFrame() {}
@@ -593,14 +606,13 @@
}
}
- private static class MessageFrame extends CommFrame implements Externalizable {
+ protected static class MessageFrame extends CommFrame implements Externalizable {
private static final long serialVersionUID = -1112437852498126297L;
String method;
Object[] args;
// Used for deserialization
- @SuppressWarnings("unused")
public MessageFrame() {
}
diff --git a/src/test/java/org/apache/ode/jacob/examples/helloworld/HelloWorld.java b/src/test/java/org/apache/ode/jacob/examples/helloworld/HelloWorld.java
index 524d350..053d049 100644
--- a/src/test/java/org/apache/ode/jacob/examples/helloworld/HelloWorld.java
+++ b/src/test/java/org/apache/ode/jacob/examples/helloworld/HelloWorld.java
@@ -30,6 +30,8 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.smile.SmileFactory;
+import com.fasterxml.jackson.dataformat.smile.SmileGenerator;
/**
* Simple Hello World example to showcase different
@@ -254,13 +256,23 @@
public static void main(String args[]) throws Exception {
// enable logging
//BasicConfigurator.configure();
- long start = System.currentTimeMillis();
- ObjectMapper mapper = new ObjectMapper();
+
+ SmileFactory sf = null;
+ // // enable smile:
+ // sf = new SmileFactory();
+ // sf.enable(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES);
+ // sf.enable(SmileGenerator.Feature.ENCODE_BINARY_AS_7BIT);
+
+ ObjectMapper mapper = new ObjectMapper(sf);
+
+
JacksonExecutionQueueImpl.configureMapper(mapper);
JacobVPU vpu = new JacobVPU();
JacksonExecutionQueueImpl queue = new JacksonExecutionQueueImpl();
vpu.setContext(queue);
+
+ long start = System.currentTimeMillis();
vpu.inject(new HelloWorld());
while (vpu.execute()) {
queue = loadAndRestoreQueue(mapper, (JacksonExecutionQueueImpl)vpu.getContext());
@@ -268,8 +280,8 @@
System.out.println(vpu.isComplete() ? "<0>" : ".");
//vpu.dumpState();
}
- vpu.dumpState();
System.out.println("Runtime in ms: " + (System.currentTimeMillis() - start));
+ vpu.dumpState();
}
public static JacksonExecutionQueueImpl loadAndRestoreQueue(ObjectMapper mapper, JacksonExecutionQueueImpl in) throws Exception {