| import java.io.*; |
| |
| import org.codehaus.jackson.*; |
| import org.codehaus.jackson.map.*; |
| |
| /** |
| * Micro-benchmark for comparing performance of bean deserialization |
| * using three methods: tree (JsonNode) deserialization; method-based |
| * bean deserialization and field-based bean deserialization. |
| */ |
| 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; |
| long y; |
| String name; |
| |
| public void setX(int v) { x = v; } |
| public void setY(long v) { y = v; } |
| public void setName(String v) { name = v; } |
| } |
| |
| final static class FieldBean |
| { |
| public FieldBean() { } |
| public FieldBean(FieldBean2 bean, |
| FieldBean2 bean2, |
| FieldBean2 bean3, |
| FieldBean2 bean4) |
| { |
| this.bean = bean; |
| this.bean2 = bean2; |
| this.bean3 = bean3; |
| this.bean4 = bean4; |
| } |
| |
| public FieldBean2 bean, bean2, bean3, bean4; |
| } |
| |
| final static class FieldBean2 { |
| public int x; |
| public long y; |
| public String name; |
| |
| public FieldBean2() { } |
| |
| public FieldBean2(int x, long y, String name) { |
| this.x = x; |
| this.y = y; |
| this.name = 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 = 20000; |
| _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(); |
| } |
| } |