package perf;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
abstract class ObjectWriterTestBase<T1,T2>
{
protected int hash;
protected abstract int targetSizeMegs();
protected void test(ObjectMapper mapper,
String desc1, T1 inputValue1, Class<? extends T1> inputClass1,
String desc2, T2 inputValue2, Class<? extends T2> inputClass2)
throws Exception
{
final int REPS;
{
final byte[] input1 = mapper.writeValueAsBytes(inputValue1);
final byte[] input2 = mapper.writeValueAsBytes(inputValue2);
// Let's try to guestimate suitable size, N megs of output
REPS = (int) ((double) (targetSizeMegs() * 1000 * 1000) / (double) input1.length);
System.out.printf("Read %d bytes to bind (%d as array); will do %d repetitions\n",
input1.length, input2.length, REPS);
}
final ObjectWriter writer0 = mapper.writer().with(SerializationFeature.EAGER_SERIALIZER_FETCH);
final ObjectWriter writer1 = writer0.forType(inputClass1);
final ObjectWriter writer2 = writer0.forType(inputClass2);
int i = 0;
int roundsDone = 0;
final int TYPES = 2;
// Skip first 5 seconds
long startMeasure = System.currentTimeMillis() + 5000L;
System.out.print("Warming up");
final double[] timesMsec = new double[TYPES];
while (true) {
final int round = (i % TYPES);
final boolean lf = (++i % TYPES) == 0;
String msg;
ObjectWriter writer;
Object value;
switch (round) {
case 0:
msg = desc1;
writer = writer1;
value = inputValue1;
break;
case 1:
msg = desc2;
writer = writer2;
value = inputValue2;
break;
default:
throw new Error();
}
double msecs = testSer(REPS, value, writer);
// skip first N seconds to let results stabilize
if (startMeasure > 0L) {
if ((round != 0) || (System.currentTimeMillis() < startMeasure)) {
System.out.print(".");
continue;
}
startMeasure = 0L;
System.out.println();
System.out.println("Starting measurements...");
Thread.sleep(250L);
System.out.println();
}
timesMsec[round] += msecs;
if ((i % 17) == 0) {
System.out.println("[GC]");
Thread.sleep(100L);
System.gc();
Thread.sleep(100L);
}
System.out.printf("Test '%s' [hash: 0x%s] -> %.1f msecs\n", msg, hash, msecs);
Thread.sleep(50L);
if (!lf) {
continue;
}
if ((++roundsDone % 3) == 0) {
double den = (double) roundsDone;
System.out.printf("Averages after %d rounds (%s/%s): %.1f / %.1f msecs\n",
roundsDone, desc1, desc2,
timesMsec[0] / den, timesMsec[1] / den);
}
System.out.println();
}
}
protected double testSer(int REPS, Object value, ObjectWriter writer) throws Exception
{
final NopOutputStream out = new NopOutputStream();
long start = System.nanoTime();
while (--REPS >= 0) {
writer.writeValue(out, value);
}
hash = out.size();
long nanos = System.nanoTime() - start;
out.close();
return _msecsFromNanos(nanos);
}
protected final double _msecsFromNanos(long nanos) {
return (nanos / 1000000.0);
}
}