xref: /aosp_15_r20/external/jackson-databind/src/test/java/perf/ObjectReaderTestBase.java (revision 0ed15c778abdfe0f5f51f6133673e1619d6e56e4)
1*0ed15c77SAndroid Build Coastguard Worker package perf;
2*0ed15c77SAndroid Build Coastguard Worker 
3*0ed15c77SAndroid Build Coastguard Worker import java.io.*;
4*0ed15c77SAndroid Build Coastguard Worker 
5*0ed15c77SAndroid Build Coastguard Worker import com.fasterxml.jackson.databind.*;
6*0ed15c77SAndroid Build Coastguard Worker 
7*0ed15c77SAndroid Build Coastguard Worker abstract class ObjectReaderTestBase
8*0ed15c77SAndroid Build Coastguard Worker {
9*0ed15c77SAndroid Build Coastguard Worker     protected final static int WARMUP_ROUNDS = 5;
10*0ed15c77SAndroid Build Coastguard Worker 
11*0ed15c77SAndroid Build Coastguard Worker     protected String _desc1, _desc2;
12*0ed15c77SAndroid Build Coastguard Worker 
13*0ed15c77SAndroid Build Coastguard Worker     protected int hash;
14*0ed15c77SAndroid Build Coastguard Worker     protected long startMeasure = System.currentTimeMillis() + 5000L;
15*0ed15c77SAndroid Build Coastguard Worker     protected int roundsDone = 0;
16*0ed15c77SAndroid Build Coastguard Worker     protected int REPS;
17*0ed15c77SAndroid Build Coastguard Worker     private double[] timeMsecs;
18*0ed15c77SAndroid Build Coastguard Worker 
targetSizeMegs()19*0ed15c77SAndroid Build Coastguard Worker     protected abstract int targetSizeMegs();
20*0ed15c77SAndroid Build Coastguard Worker 
testFromBytes(ObjectMapper mapper1, String desc1, Object inputValue1, Class<?> inputClass1, ObjectMapper mapper2, String desc2, Object inputValue2, Class<?> inputClass2)21*0ed15c77SAndroid Build Coastguard Worker     protected void testFromBytes(ObjectMapper mapper1, String desc1,
22*0ed15c77SAndroid Build Coastguard Worker             Object inputValue1, Class<?> inputClass1,
23*0ed15c77SAndroid Build Coastguard Worker             ObjectMapper mapper2, String desc2,
24*0ed15c77SAndroid Build Coastguard Worker             Object inputValue2, Class<?> inputClass2)
25*0ed15c77SAndroid Build Coastguard Worker         throws Exception
26*0ed15c77SAndroid Build Coastguard Worker     {
27*0ed15c77SAndroid Build Coastguard Worker         final byte[] byteInput1 = mapper1.writeValueAsBytes(inputValue1);
28*0ed15c77SAndroid Build Coastguard Worker         final byte[] byteInput2 = mapper2.writeValueAsBytes(inputValue2);
29*0ed15c77SAndroid Build Coastguard Worker         // Let's try to guestimate suitable size... to get to N megs to process
30*0ed15c77SAndroid Build Coastguard Worker         REPS = (int) ((double) (targetSizeMegs() * 1000 * 1000) / (double) byteInput1.length);
31*0ed15c77SAndroid Build Coastguard Worker 
32*0ed15c77SAndroid Build Coastguard Worker         // sanity check:
33*0ed15c77SAndroid Build Coastguard Worker         /*T1 back1 =*/ mapper1.readValue(byteInput1, inputClass1);
34*0ed15c77SAndroid Build Coastguard Worker         /*T2 back2 =*/ mapper2.readValue(byteInput2, inputClass2);
35*0ed15c77SAndroid Build Coastguard Worker         System.out.println("Input successfully round-tripped for both styles...");
36*0ed15c77SAndroid Build Coastguard Worker 
37*0ed15c77SAndroid Build Coastguard Worker         _desc1 = String.format("%s (%d bytes)", desc1, byteInput1.length);
38*0ed15c77SAndroid Build Coastguard Worker         _desc2 = String.format("%s (%d bytes)", desc2, byteInput2.length);
39*0ed15c77SAndroid Build Coastguard Worker 
40*0ed15c77SAndroid Build Coastguard Worker         doTest(mapper1, byteInput1, inputClass1, mapper2, byteInput2, inputClass2);
41*0ed15c77SAndroid Build Coastguard Worker     }
42*0ed15c77SAndroid Build Coastguard Worker 
testFromString(ObjectMapper mapper1, String desc1, Object inputValue1, Class<?> inputClass1, ObjectMapper mapper2, String desc2, Object inputValue2, Class<?> inputClass2)43*0ed15c77SAndroid Build Coastguard Worker     protected void testFromString(ObjectMapper mapper1, String desc1,
44*0ed15c77SAndroid Build Coastguard Worker             Object inputValue1, Class<?> inputClass1,
45*0ed15c77SAndroid Build Coastguard Worker             ObjectMapper mapper2, String desc2,
46*0ed15c77SAndroid Build Coastguard Worker             Object inputValue2, Class<?> inputClass2)
47*0ed15c77SAndroid Build Coastguard Worker         throws Exception
48*0ed15c77SAndroid Build Coastguard Worker     {
49*0ed15c77SAndroid Build Coastguard Worker         final String input1 = mapper1.writeValueAsString(inputValue1);
50*0ed15c77SAndroid Build Coastguard Worker         final String input2 = mapper2.writeValueAsString(inputValue2);
51*0ed15c77SAndroid Build Coastguard Worker         // Let's try to guestimate suitable size... to get to N megs to process
52*0ed15c77SAndroid Build Coastguard Worker         REPS = (int) ((double) (targetSizeMegs() * 1000 * 1000) / (double) input1.length());
53*0ed15c77SAndroid Build Coastguard Worker         _desc1 = String.format("%s (%d chars)", desc1, input1.length());
54*0ed15c77SAndroid Build Coastguard Worker         _desc2 = String.format("%s (%d chars)", desc2, input2.length());
55*0ed15c77SAndroid Build Coastguard Worker 
56*0ed15c77SAndroid Build Coastguard Worker         // sanity check:
57*0ed15c77SAndroid Build Coastguard Worker         /*T1 back1 =*/ mapper1.readValue(input1, inputClass1);
58*0ed15c77SAndroid Build Coastguard Worker         /*T2 back2 =*/ mapper2.readValue(input2, inputClass2);
59*0ed15c77SAndroid Build Coastguard Worker         System.out.println("Input successfully round-tripped for both styles...");
60*0ed15c77SAndroid Build Coastguard Worker 
61*0ed15c77SAndroid Build Coastguard Worker         doTest(mapper1, input1, inputClass1, mapper2, input2, inputClass2);
62*0ed15c77SAndroid Build Coastguard Worker     }
63*0ed15c77SAndroid Build Coastguard Worker 
doTest(ObjectMapper mapper1, byte[] byteInput1, Class<?> inputClass1, ObjectMapper mapper2, byte[] byteInput2, Class<?> inputClass2)64*0ed15c77SAndroid Build Coastguard Worker     protected void doTest(ObjectMapper mapper1, byte[] byteInput1, Class<?> inputClass1,
65*0ed15c77SAndroid Build Coastguard Worker             ObjectMapper mapper2, byte[] byteInput2, Class<?> inputClass2)
66*0ed15c77SAndroid Build Coastguard Worker         throws Exception
67*0ed15c77SAndroid Build Coastguard Worker     {
68*0ed15c77SAndroid Build Coastguard Worker         System.out.printf("Read %d bytes to bind (%d as array); will do %d repetitions\n",
69*0ed15c77SAndroid Build Coastguard Worker                 byteInput1.length, byteInput2.length, REPS);
70*0ed15c77SAndroid Build Coastguard Worker         System.out.print("Warming up");
71*0ed15c77SAndroid Build Coastguard Worker 
72*0ed15c77SAndroid Build Coastguard Worker         final ObjectReader jsonReader = mapper1.reader()
73*0ed15c77SAndroid Build Coastguard Worker                 .forType(inputClass1);
74*0ed15c77SAndroid Build Coastguard Worker         final ObjectReader arrayReader = mapper2.reader()
75*0ed15c77SAndroid Build Coastguard Worker                 .forType(inputClass2);
76*0ed15c77SAndroid Build Coastguard Worker 
77*0ed15c77SAndroid Build Coastguard Worker         int i = 0;
78*0ed15c77SAndroid Build Coastguard Worker         final int TYPES = 2;
79*0ed15c77SAndroid Build Coastguard Worker 
80*0ed15c77SAndroid Build Coastguard Worker         timeMsecs = new double[TYPES];
81*0ed15c77SAndroid Build Coastguard Worker 
82*0ed15c77SAndroid Build Coastguard Worker         while (true) {
83*0ed15c77SAndroid Build Coastguard Worker             Thread.sleep(100L);
84*0ed15c77SAndroid Build Coastguard Worker             final int type = (i++ % TYPES);
85*0ed15c77SAndroid Build Coastguard Worker 
86*0ed15c77SAndroid Build Coastguard Worker             String msg;
87*0ed15c77SAndroid Build Coastguard Worker             double msesc;
88*0ed15c77SAndroid Build Coastguard Worker 
89*0ed15c77SAndroid Build Coastguard Worker             switch (type) {
90*0ed15c77SAndroid Build Coastguard Worker             case 0:
91*0ed15c77SAndroid Build Coastguard Worker                 msg = _desc1;
92*0ed15c77SAndroid Build Coastguard Worker                 msesc = testDeser1(REPS, byteInput1, jsonReader);
93*0ed15c77SAndroid Build Coastguard Worker                 break;
94*0ed15c77SAndroid Build Coastguard Worker             case 1:
95*0ed15c77SAndroid Build Coastguard Worker                 msg = _desc2;
96*0ed15c77SAndroid Build Coastguard Worker                 msesc = testDeser2(REPS, byteInput2, arrayReader);
97*0ed15c77SAndroid Build Coastguard Worker                 break;
98*0ed15c77SAndroid Build Coastguard Worker             default:
99*0ed15c77SAndroid Build Coastguard Worker                 throw new Error();
100*0ed15c77SAndroid Build Coastguard Worker             }
101*0ed15c77SAndroid Build Coastguard Worker             updateStats(type, (i % 17) == 0, msg, msesc);
102*0ed15c77SAndroid Build Coastguard Worker         }
103*0ed15c77SAndroid Build Coastguard Worker     }
104*0ed15c77SAndroid Build Coastguard Worker 
doTest(ObjectMapper mapper1, String input1, Class<?> inputClass1, ObjectMapper mapper2, String input2, Class<?> inputClass2)105*0ed15c77SAndroid Build Coastguard Worker     protected void doTest(ObjectMapper mapper1, String input1, Class<?> inputClass1,
106*0ed15c77SAndroid Build Coastguard Worker             ObjectMapper mapper2, String input2, Class<?> inputClass2)
107*0ed15c77SAndroid Build Coastguard Worker         throws Exception
108*0ed15c77SAndroid Build Coastguard Worker     {
109*0ed15c77SAndroid Build Coastguard Worker         System.out.printf("Read %d bytes to bind (%d as array); will do %d repetitions\n",
110*0ed15c77SAndroid Build Coastguard Worker                 input1.length(), input2.length(), REPS);
111*0ed15c77SAndroid Build Coastguard Worker         System.out.print("Warming up");
112*0ed15c77SAndroid Build Coastguard Worker 
113*0ed15c77SAndroid Build Coastguard Worker         final ObjectReader jsonReader = mapper1.reader()
114*0ed15c77SAndroid Build Coastguard Worker                 .with(DeserializationFeature.EAGER_DESERIALIZER_FETCH)
115*0ed15c77SAndroid Build Coastguard Worker                 .forType(inputClass1);
116*0ed15c77SAndroid Build Coastguard Worker         final ObjectReader arrayReader = mapper2.reader()
117*0ed15c77SAndroid Build Coastguard Worker                 .with(DeserializationFeature.EAGER_DESERIALIZER_FETCH)
118*0ed15c77SAndroid Build Coastguard Worker                 .forType(inputClass2);
119*0ed15c77SAndroid Build Coastguard Worker 
120*0ed15c77SAndroid Build Coastguard Worker         int i = 0;
121*0ed15c77SAndroid Build Coastguard Worker         final int TYPES = 2;
122*0ed15c77SAndroid Build Coastguard Worker 
123*0ed15c77SAndroid Build Coastguard Worker         timeMsecs = new double[TYPES];
124*0ed15c77SAndroid Build Coastguard Worker 
125*0ed15c77SAndroid Build Coastguard Worker         while (true) {
126*0ed15c77SAndroid Build Coastguard Worker             Thread.sleep(100L);
127*0ed15c77SAndroid Build Coastguard Worker             int type = (i++ % TYPES);
128*0ed15c77SAndroid Build Coastguard Worker             String msg;
129*0ed15c77SAndroid Build Coastguard Worker             double msecs;
130*0ed15c77SAndroid Build Coastguard Worker 
131*0ed15c77SAndroid Build Coastguard Worker             switch (type) {
132*0ed15c77SAndroid Build Coastguard Worker             case 0:
133*0ed15c77SAndroid Build Coastguard Worker                 msg = _desc1;
134*0ed15c77SAndroid Build Coastguard Worker                 msecs = testDeser1(REPS, input1, jsonReader);
135*0ed15c77SAndroid Build Coastguard Worker                 break;
136*0ed15c77SAndroid Build Coastguard Worker             case 1:
137*0ed15c77SAndroid Build Coastguard Worker                 msg = _desc2;
138*0ed15c77SAndroid Build Coastguard Worker                 msecs = testDeser2(REPS, input2, arrayReader);
139*0ed15c77SAndroid Build Coastguard Worker                 break;
140*0ed15c77SAndroid Build Coastguard Worker             default:
141*0ed15c77SAndroid Build Coastguard Worker                 throw new Error();
142*0ed15c77SAndroid Build Coastguard Worker             }
143*0ed15c77SAndroid Build Coastguard Worker             updateStats(type, (i % 17) == 0, msg, msecs);
144*0ed15c77SAndroid Build Coastguard Worker         }
145*0ed15c77SAndroid Build Coastguard Worker     }
146*0ed15c77SAndroid Build Coastguard Worker 
updateStats(int type, boolean doGc, String msg, double msecs)147*0ed15c77SAndroid Build Coastguard Worker     private void updateStats(int type, boolean doGc, String msg, double msecs)
148*0ed15c77SAndroid Build Coastguard Worker         throws Exception
149*0ed15c77SAndroid Build Coastguard Worker     {
150*0ed15c77SAndroid Build Coastguard Worker         final boolean lf = (type == (timeMsecs.length - 1));
151*0ed15c77SAndroid Build Coastguard Worker 
152*0ed15c77SAndroid Build Coastguard Worker         if (startMeasure == 0L) { // skip first N seconds
153*0ed15c77SAndroid Build Coastguard Worker             timeMsecs[type] += msecs;
154*0ed15c77SAndroid Build Coastguard Worker         } else {
155*0ed15c77SAndroid Build Coastguard Worker             if (lf) {
156*0ed15c77SAndroid Build Coastguard Worker                 if (System.currentTimeMillis() >= startMeasure) {
157*0ed15c77SAndroid Build Coastguard Worker                     startMeasure = 0L;
158*0ed15c77SAndroid Build Coastguard Worker                     System.out.println(" complete!");
159*0ed15c77SAndroid Build Coastguard Worker                 } else {
160*0ed15c77SAndroid Build Coastguard Worker                     System.out.print(".");
161*0ed15c77SAndroid Build Coastguard Worker                 }
162*0ed15c77SAndroid Build Coastguard Worker             }
163*0ed15c77SAndroid Build Coastguard Worker             return;
164*0ed15c77SAndroid Build Coastguard Worker         }
165*0ed15c77SAndroid Build Coastguard Worker 
166*0ed15c77SAndroid Build Coastguard Worker         System.out.printf("Test '%s' [hash: 0x%s] -> %.1f msecs\n", msg, Integer.toHexString(hash), msecs);
167*0ed15c77SAndroid Build Coastguard Worker         if (lf) {
168*0ed15c77SAndroid Build Coastguard Worker             ++roundsDone;
169*0ed15c77SAndroid Build Coastguard Worker             if ((roundsDone % 3) == 0 ) {
170*0ed15c77SAndroid Build Coastguard Worker                 double den = (double) roundsDone;
171*0ed15c77SAndroid Build Coastguard Worker                 System.out.printf("Averages after %d rounds (%s/%s): %.1f / %.1f msecs\n",
172*0ed15c77SAndroid Build Coastguard Worker                         (int) den, _desc1, _desc2,
173*0ed15c77SAndroid Build Coastguard Worker                         timeMsecs[0] / den, timeMsecs[1] / den);
174*0ed15c77SAndroid Build Coastguard Worker             }
175*0ed15c77SAndroid Build Coastguard Worker             System.out.println();
176*0ed15c77SAndroid Build Coastguard Worker         }
177*0ed15c77SAndroid Build Coastguard Worker         if (doGc) {
178*0ed15c77SAndroid Build Coastguard Worker             System.out.println("[GC]");
179*0ed15c77SAndroid Build Coastguard Worker             Thread.sleep(100L);
180*0ed15c77SAndroid Build Coastguard Worker             System.gc();
181*0ed15c77SAndroid Build Coastguard Worker             Thread.sleep(100L);
182*0ed15c77SAndroid Build Coastguard Worker         }
183*0ed15c77SAndroid Build Coastguard Worker     }
184*0ed15c77SAndroid Build Coastguard Worker 
testDeser1(int reps, byte[] input, ObjectReader reader)185*0ed15c77SAndroid Build Coastguard Worker     protected double testDeser1(int reps, byte[] input, ObjectReader reader) throws Exception {
186*0ed15c77SAndroid Build Coastguard Worker         return _testDeser(reps, input, reader);
187*0ed15c77SAndroid Build Coastguard Worker     }
testDeser2(int reps, byte[] input, ObjectReader reader)188*0ed15c77SAndroid Build Coastguard Worker     protected double testDeser2(int reps, byte[] input, ObjectReader reader) throws Exception {
189*0ed15c77SAndroid Build Coastguard Worker         return _testDeser(reps, input, reader);
190*0ed15c77SAndroid Build Coastguard Worker     }
191*0ed15c77SAndroid Build Coastguard Worker 
_testDeser(int reps, byte[] input, ObjectReader reader)192*0ed15c77SAndroid Build Coastguard Worker     protected final double _testDeser(int reps, byte[] input, ObjectReader reader) throws Exception
193*0ed15c77SAndroid Build Coastguard Worker     {
194*0ed15c77SAndroid Build Coastguard Worker         long start = System.nanoTime();
195*0ed15c77SAndroid Build Coastguard Worker         Object result = null;
196*0ed15c77SAndroid Build Coastguard Worker         while (--reps >= 0) {
197*0ed15c77SAndroid Build Coastguard Worker             result = reader.readValue(input);
198*0ed15c77SAndroid Build Coastguard Worker         }
199*0ed15c77SAndroid Build Coastguard Worker         hash = result.hashCode();
200*0ed15c77SAndroid Build Coastguard Worker         // return microseconds
201*0ed15c77SAndroid Build Coastguard Worker         return _msecsFromNanos(System.nanoTime() - start);
202*0ed15c77SAndroid Build Coastguard Worker     }
203*0ed15c77SAndroid Build Coastguard Worker 
testDeser1(int reps, String input, ObjectReader reader)204*0ed15c77SAndroid Build Coastguard Worker     protected double testDeser1(int reps, String input, ObjectReader reader) throws Exception {
205*0ed15c77SAndroid Build Coastguard Worker         return _testDeser(reps, input, reader);
206*0ed15c77SAndroid Build Coastguard Worker     }
207*0ed15c77SAndroid Build Coastguard Worker 
testDeser2(int reps, String input, ObjectReader reader)208*0ed15c77SAndroid Build Coastguard Worker     protected double testDeser2(int reps, String input, ObjectReader reader) throws Exception {
209*0ed15c77SAndroid Build Coastguard Worker         return _testDeser(reps, input, reader);
210*0ed15c77SAndroid Build Coastguard Worker     }
211*0ed15c77SAndroid Build Coastguard Worker 
_testDeser(int reps, String input, ObjectReader reader)212*0ed15c77SAndroid Build Coastguard Worker     protected final double _testDeser(int reps, String input, ObjectReader reader) throws Exception
213*0ed15c77SAndroid Build Coastguard Worker     {
214*0ed15c77SAndroid Build Coastguard Worker         long start = System.nanoTime();
215*0ed15c77SAndroid Build Coastguard Worker         Object result = null;
216*0ed15c77SAndroid Build Coastguard Worker         while (--reps >= 0) {
217*0ed15c77SAndroid Build Coastguard Worker             result = reader.readValue(input);
218*0ed15c77SAndroid Build Coastguard Worker         }
219*0ed15c77SAndroid Build Coastguard Worker         hash = result.hashCode();
220*0ed15c77SAndroid Build Coastguard Worker         return _msecsFromNanos(System.nanoTime() - start);
221*0ed15c77SAndroid Build Coastguard Worker     }
222*0ed15c77SAndroid Build Coastguard Worker 
_msecsFromNanos(long nanos)223*0ed15c77SAndroid Build Coastguard Worker     protected final double _msecsFromNanos(long nanos) {
224*0ed15c77SAndroid Build Coastguard Worker         return (nanos / 1000000.0);
225*0ed15c77SAndroid Build Coastguard Worker     }
226*0ed15c77SAndroid Build Coastguard Worker 
readAll(String filename)227*0ed15c77SAndroid Build Coastguard Worker     protected static byte[] readAll(String filename) throws IOException
228*0ed15c77SAndroid Build Coastguard Worker     {
229*0ed15c77SAndroid Build Coastguard Worker         File f = new File(filename);
230*0ed15c77SAndroid Build Coastguard Worker         ByteArrayOutputStream bytes = new ByteArrayOutputStream((int) f.length());
231*0ed15c77SAndroid Build Coastguard Worker         byte[] buffer = new byte[4000];
232*0ed15c77SAndroid Build Coastguard Worker         int count;
233*0ed15c77SAndroid Build Coastguard Worker         FileInputStream in = new FileInputStream(f);
234*0ed15c77SAndroid Build Coastguard Worker 
235*0ed15c77SAndroid Build Coastguard Worker         while ((count = in.read(buffer)) > 0) {
236*0ed15c77SAndroid Build Coastguard Worker             bytes.write(buffer, 0, count);
237*0ed15c77SAndroid Build Coastguard Worker         }
238*0ed15c77SAndroid Build Coastguard Worker         in.close();
239*0ed15c77SAndroid Build Coastguard Worker         return bytes.toByteArray();
240*0ed15c77SAndroid Build Coastguard Worker     }
241*0ed15c77SAndroid Build Coastguard Worker }
242