Improved simple ser/deser perf tests to see if and how speed of field/accessor+mutator
methods differ.
diff --git a/build.xml b/build.xml
index 467e853..e6c8207 100644
--- a/build.xml
+++ b/build.xml
@@ -239,7 +239,7 @@
<target name="compile.perf" depends="compile.main">
<mkdir dir="${dir.build.classes.perf}" />
<!-- Let's also compile micro-benchmarks... -->
- <javac srcdir="${dir.src}/perf" destdir="${dir.build.classes.perf}" debug="false"
+ <javac srcdir="${dir.src}/perf" destdir="${dir.build.classes.perf}" debug="true"
>
<classpath>
<fileset dir="${dir.lib}/perf">
diff --git a/run.sh b/run.sh
index 09d11df..9091e63 100755
--- a/run.sh
+++ b/run.sh
@@ -2,5 +2,5 @@
java -Xmx48m -server\
-cp lib/junit/junit-3.8.1.jar\
-:build/classes/core:build/classes/mapper:build/classes/extra\
+:build/classes/core:build/classes/mapper:build/classes/extra:build/classes/perf\
$*
diff --git a/src/perf/TestDeserPerf.java b/src/perf/TestDeserPerf.java
new file mode 100644
index 0000000..fe8edb7
--- /dev/null
+++ b/src/perf/TestDeserPerf.java
@@ -0,0 +1,115 @@
+import java.io.*;
+
+import org.codehaus.jackson.*;
+import org.codehaus.jackson.map.*;
+
+public final class TestDeserPerf
+{
+ /*
+ /////////////////////////////////////////////////////
+ // Bean classes
+ /////////////////////////////////////////////////////
+ */
+
+ static class Bean {
+ Bean2 bean, bean2, bean3, bean4;
+
+ public void setBean(Bean2 v) { bean = v; }
+ public void setBean2(Bean2 v) { bean2 = v; }
+ public void setBean3(Bean2 v) { bean3 = v; }
+ public void setBean4(Bean2 v) { bean4 = v; }
+ }
+
+ static class Bean2 {
+ int x;
+ String name;
+
+ public void setX(int v) { x = v; }
+ public void setName(String v) { name = v; }
+ }
+
+ final static class FieldBean {
+ public FieldBean2 bean, bean2, bean3, bean4;
+ }
+
+ final static class FieldBean2 {
+ public int x;
+ public String name;
+ }
+
+ private final int REPS;
+ private final ObjectMapper _mapper;
+ private final byte[] _data;
+
+ public TestDeserPerf()
+ throws Exception
+ {
+ // Let's try to guestimate suitable size, to spend enough (but not too much) time per round
+ REPS = 60000;
+ _mapper = new ObjectMapper();
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ _mapper.writeValue(result, new FieldBean());
+ _data = result.toByteArray();
+ }
+
+ public void test()
+ throws Exception
+ {
+ int i = 0;
+ int sum = 0;
+
+ System.out.println("START: content size "+_data.length+" bytes");
+ ByteArrayInputStream in = new ByteArrayInputStream(_data);
+
+ while (true) {
+ try { Thread.sleep(100L); } catch (InterruptedException ie) { }
+ int round = (i++ % 3);
+
+ long curr = System.currentTimeMillis();
+ String msg;
+ boolean lf = (round == 0);
+
+ switch (round) {
+
+ case 0:
+ msg = "Jackson, object+SET";
+ sum += testDeser(REPS, in, Bean.class);
+ break;
+ case 1:
+ msg = "Jackson, object+Field";
+ sum += testDeser(REPS, in, FieldBean.class);
+ break;
+ case 2:
+ msg = "Jackson, tree";
+ sum += testDeser(REPS, in, JsonNode.class);
+ break;
+ default:
+ throw new Error("Internal error");
+ }
+
+ curr = System.currentTimeMillis() - curr;
+ if (lf) {
+ System.out.println();
+ }
+ System.out.println("Test '"+msg+"' -> "+curr+" msecs ("
+ +(sum & 0xFF)+").");
+
+ }
+ }
+
+ protected <T> int testDeser(int reps, ByteArrayInputStream in, Class<T> beanType)
+ throws Exception
+ {
+ T result = null;
+ for (int i = 0; i < reps; ++i) {
+ in.reset();
+ result = _mapper.readValue(in, beanType);
+ }
+ return result.hashCode(); // just to get some non-optimizable number
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ new TestDeserPerf().test();
+ }
+}
diff --git a/src/perf/TestSerPerf.java b/src/perf/TestSerPerf.java
index 1fa77fc..4434e57 100644
--- a/src/perf/TestSerPerf.java
+++ b/src/perf/TestSerPerf.java
@@ -2,7 +2,6 @@
import org.codehaus.jackson.*;
import org.codehaus.jackson.map.*;
-import org.codehaus.jackson.util.BufferRecycler;
public final class TestSerPerf
{
@@ -12,7 +11,7 @@
/////////////////////////////////////////////////////
*/
- class NonFinalBean {
+ static class NonFinalBean {
final NonFinalBean2 _bean = new NonFinalBean2();
public NonFinalBean2 getBean() { return _bean; }
@@ -21,12 +20,12 @@
public NonFinalBean2 getBean4() { return _bean; }
}
- class NonFinalBean2 {
+ static class NonFinalBean2 {
public int getX() { return 3; }
public String getName() { return "foobar"; }
}
- final class FinalBean {
+ final static class FinalBean {
final FinalBean2 _bean = new FinalBean2();
public FinalBean2 getBean() { return _bean; }
@@ -35,21 +34,36 @@
public FinalBean2 getBean4() { return _bean; }
}
- final class FinalBean2 {
+ final static class FinalBean2 {
+ public int getX() { return 3; }
+ public String getName() { return "foobar"; }
+ }
+
+ final static class FinalFieldBean {
+ private final FinalFieldBean2 _bean = new FinalFieldBean2();
+
+ public FinalFieldBean2 fieldBean = _bean;
+ public FinalFieldBean2 fieldBean2 = _bean;
+ public FinalFieldBean2 fieldBean3 = _bean;
+ public FinalFieldBean2 fieldBean4 = _bean;
+ }
+
+ final static class FinalFieldBean2 {
public int getX() { return 3; }
public String getName() { return "foobar"; }
}
private final int REPS;
-
- private final static int TEST_PER_GC = 15;
+ private final ObjectMapper _mapper;
final Object _finalBean = new FinalBean();
+ final Object _finalFieldBean = new FinalFieldBean();
final Object _nonFinalBean = new NonFinalBean();
public TestSerPerf()
throws Exception
{
+ _mapper = new ObjectMapper();
// Let's try to guestimate suitable size... to get to 50 megs processed
REPS = 40000;
}
@@ -64,11 +78,11 @@
// Let's create tree from objects
testObjectSer(_finalBean, 1, result);
- final JsonNode _tree = new TreeMapper().readTree(result.toByteArray());
+ final JsonNode _tree = _mapper.readTree(new JsonFactory().createJsonParser(result.toByteArray()));
while (true) {
try { Thread.sleep(100L); } catch (InterruptedException ie) { }
- int round = (i++ % 3);
+ int round = (i++ % 4);
long curr = System.currentTimeMillis();
String msg;
@@ -77,14 +91,18 @@
switch (round) {
case 0:
- msg = "Jackson, object, final";
+ msg = "Jackson, object+GET, final";
sum += testObjectSer(_finalBean, REPS, result);
break;
case 1:
+ msg = "Jackson, object+Field, final";
+ sum += testObjectSer(_finalFieldBean, REPS, result);
+ break;
+ case 2:
msg = "Jackson, object, nonfinal";
sum += testObjectSer(_nonFinalBean, REPS, result);
break;
- case 2:
+ case 3:
msg = "Jackson, tree";
sum += testTreeSer(_tree, REPS, result);
break;
@@ -98,37 +116,27 @@
}
System.out.println("Test '"+msg+"' -> "+curr+" msecs ("
+(sum & 0xFF)+").");
-
-
- if ((i % TEST_PER_GC) == 0) {
- System.out.println("[GC]");
- try { Thread.sleep(100L); } catch (InterruptedException ie) { }
- System.gc();
- try { Thread.sleep(100L); } catch (InterruptedException ie) { }
- }
}
}
protected int testObjectSer(Object value, int reps, ByteArrayOutputStream result)
throws Exception
{
- ObjectMapper mapper = new ObjectMapper();
for (int i = 0; i < reps; ++i) {
result.reset();
- mapper.writeValue(result, value);
+ _mapper.writeValue(result, value);
}
- return mapper.hashCode(); // just to get some non-optimizable number
+ return _mapper.hashCode(); // just to get some non-optimizable number
}
- protected int testTreeSer(JsonNode value, int reps, ByteArrayOutputStream result)
+ protected int testTreeSer(JsonNode root, int reps, ByteArrayOutputStream result)
throws Exception
{
- TreeMapper mapper = new TreeMapper();
for (int i = 0; i < reps; ++i) {
result.reset();
- mapper.writeTree(value, result);
+ _mapper.writeValue(result, root);
}
- return mapper.hashCode(); // just to get some non-optimizable number
+ return _mapper.hashCode(); // just to get some non-optimizable number
}
public static void main(String[] args) throws Exception