Search code examples
javaperformanceperformance-testingjamon

JAMon do not work after serialization+deserialization


The flow of my performance testing needs JAMon monitor to go through these steps:

  1. created,
  2. serialized
  3. deserialized
  4. deserialized copy to be stopped

But the following scenario do not work (step 4 has no effect).

Could you provide me a workaround?

Proof with code:

public class Main {

    protected static void monitorSomething() throws InterruptedException, IOException, ClassNotFoundException{
        Monitor outerMonitor = MonitorFactory.start("outerMonitor");
        for (int i=1; i<=10; i++) {
            Monitor inner = MonitorFactory.start("myInnerMonitor");
            Monitor serializedMonitorSource = MonitorFactory.start("serializedMonitor");
            Thread.sleep(100+i);
            byte[] serialized = serialize( serializedMonitorSource );
            Monitor serializedMonitorDestination = (Monitor)deserialize( serialized );
            serializedMonitorDestination.stop();
            inner.stop();
        }
        outerMonitor.stop();
        MonitorFactory.start("mySecondMonitor")
                      .stop();

    }

    protected static void printPerformanceMeasurements(){
        for( Object monitor: MonitorFactory.getMap().values() ){
            System.out.println( monitor );  
        }

    }

    public static void main(String[] args) throws InterruptedException, IOException, ClassNotFoundException {
        monitorSomething();
        printPerformanceMeasurements();
    }

    private static byte[] serialize(Serializable serializable)  throws IOException {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
             ObjectOutput out = new ObjectOutputStream(bos)) {
            out.writeObject(serializable);
            byte[] messageBytes = bos.toByteArray();
            return messageBytes;
        }

    }

    private static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException{
        try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
             ObjectInput in = new ObjectInputStream(bis)) {
            return in.readObject();
        }         
    }
}

Output:

JAMon Label=myInnerMonitor, Units=ms.: (LastValue=114.0, Hits=10.0, Avg=114.2, Total=1142.0, Min=105.0, Max=136.0, Active=0.0, Avg Active=1.0, Max Active=1.0, First Access=Thu Feb 25 22:01:38 EET 2016, Last Access=Thu Feb 25 22:01:39 EET 2016)
JAMon Label=outerMonitor, Units=ms.: (LastValue=1143.0, Hits=1.0, Avg=1143.0, Total=1143.0, Min=1143.0, Max=1143.0, Active=0.0, Avg Active=1.0, Max Active=1.0, First Access=Thu Feb 25 22:01:39 EET 2016, Last Access=Thu Feb 25 22:01:39 EET 2016)
JAMon Label=mySecondMonitor, Units=ms.: (LastValue=0.0, Hits=1.0, Avg=0.0, Total=0.0, Min=0.0, Max=0.0, Active=0.0, Avg Active=1.0, Max Active=1.0, First Access=Thu Feb 25 22:01:39 EET 2016, Last Access=Thu Feb 25 22:01:39 EET 2016)
JAMon Label=serializedMonitor, Units=ms.: (LastValue=0.0, Hits=0.0, Avg=0.0, Total=0.0, Min=1.7976931348623157E308, Max=-1.7976931348623157E308, Active=10.0, Avg Active=0.0, Max Active=0.0, First Access=Thu Jan 01 02:00:00 EET 1970, Last Access=Thu Jan 01 02:00:00 EET 1970)
JAMon Label=com.jamonapi.Exceptions, Units=Exception: (LastValue=0.0, Hits=0.0, Avg=0.0, Total=0.0, Min=1.7976931348623157E308, Max=-1.7976931348623157E308, Active=0.0, Avg Active=0.0, Max Active=0.0, First Access=Thu Jan 01 02:00:00 EET 1970, Last Access=Thu Jan 01 02:00:00 EET 1970)

Note that none of serializedMonitor is measured (active=10)


Solution

  • A workaround is to serialize not the whole Monitor object, but only the start moment. At the measuring point, you could deserialize that moment and calculate the time difference from now. Then add the calculated value to MonitorFactory statistics pool.

    You get time execution statistics (min,max,avg). The drawback is that you lose statistics of active executions.

    Example code:

    //            Monitor serializedMonitorSource = MonitorFactory.start("serializedMonitor");
            Date measuringStartOriginal = new Date();
            byte[] serialized = serialize( measuringStartOriginal );
            Thread.sleep(100+i);
    //            Monitor serializedMonitorDestination = (Monitor)deserialize( serialized );
            Date measuringStartDeserialized = (Date)deserialize( serialized );
    //            serializedMonitorDestination.stop();
            Date measuringEnd = (new Date());
            long timeDifference =  measuringEnd.getTime() - measuringStartDeserialized.getTime();
            MonitorFactory.add( "timeDifference", "ms", timeDifference );
    

    Result:

    JAMon Label=timeDifference, Units=ms: (LastValue=110.0, Hits=10.0, Avg=106.3, Total=1063.0, Min=102.0, Max=110.0, Active=0.0, Avg Active=0.0, Max Active=0.0, First Access=Mon Feb 29 10:43:57 EET 2016, Last Access=Mon Feb 29 10:43:58 EET 2016)