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();
+    }
+}
+