Checking in Jackson 0.9.1 baseline.
diff --git a/src/perf/TestJsonPerf.java b/src/perf/TestJsonPerf.java
new file mode 100644
index 0000000..84c5be9
--- /dev/null
+++ b/src/perf/TestJsonPerf.java
@@ -0,0 +1,250 @@
+import java.io.*;
+
+import org.codehaus.jackson.*;
+import org.codehaus.jackson.io.IOContext;
+import org.codehaus.jackson.io.UTF8Reader;
+import org.codehaus.jackson.map.JavaTypeMapper;
+import org.codehaus.jackson.map.JsonTypeMapper;
+import org.codehaus.jackson.util.BufferRecycler;
+
+// json.org's reference implementation
+import org.json.*;
+// StringTree implementation
+import org.stringtree.json.JSONReader;
+// Jsontool implementation
+import com.sdicons.json.parser.JSONParser;
+// Noggit:
+//import org.apache.noggit.JSONParser;
+
+public final class TestJsonPerf
+{
+ private final static int REPS = 2500;
+
+ private final static int TEST_PER_GC = 5;
+
+ final JsonFactory mJsonFactory;
+
+ final byte[] mData;
+
+ protected int mBatchSize;
+
+ public TestJsonPerf(File f)
+ throws Exception
+ {
+ mJsonFactory = new JsonFactory();
+ mData = readData(f);
+
+ System.out.println("Read "+mData.length+" bytes from '"+f+"'");
+ System.out.println();
+ }
+
+ public void test()
+ throws Exception
+ {
+ int i = 0;
+ int sum = 0;
+
+ while (true) {
+ try { Thread.sleep(100L); } catch (InterruptedException ie) { }
+ // Use 7 to test all...
+ int round = (i++ % 2);
+
+ long curr = System.currentTimeMillis();
+ String msg;
+ boolean lf = false;
+
+ switch (round) {
+ case 0:
+ msg = "Jackson, stream";
+ sum += testJacksonStream(REPS);
+ break;
+ case 1:
+ lf = true;
+ msg = "Noggit";
+ sum += testNoggit(REPS);
+ break;
+ case 2:
+ msg = "Jackson, Java types";
+ sum += testJacksonJavaTypes(REPS);
+ break;
+ case 3:
+ msg = "Jackson, JSON types";
+ sum += testJacksonJavaTypes(REPS);
+ break;
+ case 4:
+ msg = "Json.org";
+ sum += testJsonOrg(REPS);
+ break;
+ case 5:
+ msg = "JSONTools (berlios.de)";
+ sum += testJsonTools(REPS);
+ break;
+ case 6:
+ msg = "StringTree";
+ sum += testStringTree(REPS);
+ 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)+").");
+
+
+ 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) { }
+ }
+ }
+ }
+
+ private final byte[] readData(File f)
+ throws IOException
+ {
+ int len = (int) f.length();
+ byte[] data = new byte[len];
+ int offset = 0;
+ FileInputStream fis = new FileInputStream(f);
+
+ while (len > 0) {
+ int count = fis.read(data, offset, len-offset);
+ offset += count;
+ len -= count;
+ }
+
+ return data;
+ }
+
+ protected int testJsonOrg(int reps)
+ throws Exception
+ {
+ Object ob = null;
+ for (int i = 0; i < reps; ++i) {
+ // Json.org's code only accepts Strings:
+ String input = new String(mData, "UTF-8");
+ JSONTokener tok = new JSONTokener(input);
+ ob = tok.nextValue();
+ }
+ return ob.hashCode();
+ }
+
+ protected int testJsonTools(int reps)
+ throws Exception
+ {
+ Object ob = null;
+ for (int i = 0; i < reps; ++i) {
+ // Json-tools accepts streams, yay!
+ JSONParser jp = new JSONParser(new ByteArrayInputStream(mData), "byte stream");
+ /* Hmmmh. Will we get just one object for the whole thing?
+ * Or a stream? Seems like just one
+ */
+ //while ((ob = jp.nextValue()) != null) { ; }
+ ob = jp.nextValue();
+ }
+ return ob.hashCode();
+ }
+
+ protected int testStringTree(int reps)
+ throws Exception
+ {
+ Object ob = null;
+ for (int i = 0; i < reps; ++i) {
+ // StringTree impl only accepts Strings:
+ String input = new String(mData, "UTF-8");
+ ob = new JSONReader().read(input);
+ }
+ return ob.hashCode();
+ }
+
+ protected int testNoggit(int reps)
+ throws Exception
+ {
+ ByteArrayInputStream bin = new ByteArrayInputStream(mData);
+
+ char[] cbuf = new char[mData.length];
+
+ IOContext ctxt = new IOContext(new BufferRecycler(), this);
+ int sum = 0;
+
+ for (int i = 0; i < reps; ++i) {
+ /* This may be unfair advantage (allocating buffer of exact
+ * size)? But let's do that for now
+ */
+ //char[] cbuf = new char[mData.length];
+ //InputStreamReader r = new InputStreamReader(bin, "UTF-8");
+ byte[] bbuf = ctxt.allocReadIOBuffer();
+ UTF8Reader r = new UTF8Reader(ctxt, bin, bbuf, 0, 0);
+
+ bin.reset();
+ org.apache.noggit.JSONParser jp = new org.apache.noggit.JSONParser(r, cbuf);
+ int type;
+ while ((type = jp.nextEvent()) != org.apache.noggit.JSONParser.EOF) {
+ if (type == org.apache.noggit.JSONParser.STRING) {
+ sum += jp.getString().length();
+ }
+ }
+ }
+ return sum;
+ }
+
+ protected int testJacksonStream(int reps)
+ throws Exception
+ {
+ int sum = 0;
+ for (int i = 0; i < reps; ++i) {
+ JsonParser jp = mJsonFactory.createJsonParser(new ByteArrayInputStream(mData));
+ JsonToken t;
+ while ((t = jp.nextToken()) != null) {
+ // Field names are always constructed
+ if (t == JsonToken.VALUE_STRING) {
+ sum += jp.getText().length();
+ }
+ }
+ jp.close();
+ }
+ return sum;
+ }
+
+ protected int testJacksonJavaTypes(int reps)
+ throws Exception
+ {
+ Object ob = null;
+ JavaTypeMapper mapper = new JavaTypeMapper();
+ for (int i = 0; i < reps; ++i) {
+ JsonParser jp = mJsonFactory.createJsonParser(new ByteArrayInputStream(mData));
+ ob = mapper.read(jp);
+ jp.close();
+ }
+ return ob.hashCode(); // just to get some non-optimizable number
+ }
+
+ protected int testJacksonJsonTypes(int reps)
+ throws Exception
+ {
+ Object ob = null;
+ JsonTypeMapper mapper = new JsonTypeMapper();
+ for (int i = 0; i < reps; ++i) {
+ JsonParser jp = mJsonFactory.createJsonParser(new ByteArrayInputStream(mData));
+ ob = mapper.read(jp);
+ jp.close();
+ }
+ return ob.hashCode(); // just to get some non-optimizable number
+ }
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ if (args.length != 1) {
+ System.err.println("Usage: java ... <file>");
+ System.exit(1);
+ }
+ new TestJsonPerf(new File(args[0])).test();
+ }
+}
+