package com.ikokoon.serenity;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.log4j.Logger;
import com.ikokoon.serenity.model.Method;
import com.ikokoon.serenity.model.Snapshot;
import com.ikokoon.serenity.persistence.IDataBase;
import com.ikokoon.serenity.process.Reporter;
import com.ikokoon.serenity.process.Snapshooter;
/**
* This class generates the reports for the profiled classes.
*
* <pre>
* Model:
* Class class
* List<Snapshot> snapshots
* long net
* long total
* long wait
* Date start
* Date end
* List<Method> methods
* List<Snapshot> snapshots
* long net
* long total
* long wait
* Date start
* Date end
*
* Calculations:
* 1) Calculate the total time for each method - totalMethodTime()
* Snapshots {2, 5, 3, 6, 5} = 2 + 5 + 3 + 6 + 5 = 21
* 2) Calculate the total net time for each method - totalNetMethodTime()
* Snapshot {1, 2, 4, 3, 2 } = 1 + 2 + 4 + 3 + 2 = 12
* 3) Calculate the series for the total times for the method - methodSeries()
* Snapshots {2, 5, 3, 6, 5}
* 4) Calculate the series for the net times for the method - methodNetSeries()
* Snapshot {1, 2, 4, 3, 2}
* 5) Calculate the series for the change in total time for the method - methodChangeSeries()
* Snapshots {2, 5, 3, 6, 5} = {3, -2, 3, -1}
* 6) Calculate the series for the change in net time for the method - methodNetChangeSeries()
* Snapshot {1, 2, 4, 3, 2} = {1, 2, -1, -1}
* 7) Calculate the average total time for each method - averageMethodTime()
* Snapshot {2, 5, 3, 6, 5} = (2 + 5 + 3 + 6 + 5)/5 = 21/5 = 4.2
* 8) Calculate the average net time for each method - averageMethodNetTime()
* Snapshot {1, 2, 4, 3, 2} = (1 + 2 + 4 + 3 + 2)/5 = 12/5 = 2.4
* 9) Calculate the total change for the methods - methodChange()
* Snapshots {2, 5, 3, 6, 5} = 3
* 10) Calculate the net change for the methods - methodNetChange()
* Snapshot {1, 2, 4, 3, 2} = 1
*
* Does this make sense?
* x) Calculate the average total change for the methods - averageMethodChange()
* Snapshots {2, 5, 3, 6, 5} = 3, -2, 3, -1 = 3/5 = 0.66
* xx) Calculate the average net change for the methods - averageNetMethodChange()
* Snapshot {1, 2, 4, 3, 2} = 1, 2, -1, -1 = 1/5 = 0.20
* xxx) Calculate the average change in total time for each class - averageClassTimeChange()
* xxxx) Calculate the average change in net time for each class - averageClassNetTimeChange()
*
* 1) Calculate the total time for each class - totalClassTime()
* 2) Calculate the total net time for each class - totalNetClassTime()
*
* 5) Calculate the highest average total change for the classes - highestAverageClassChange()
* 6) Calculate the highest average net change for the classes - highestAverageNetClassChange()
* 7) Calculate the highest total change for the classes - highestClassChange()
* 8) Calculate the highest net change for the classes - highestClassNetChange()
* 9) Calculate the series for the total times for the class - classSeries()
* 10) Calculate the series for the net times for the class - classNetSeries()
* 11) Calculate the series for the change in total time for the class -
* 12) Calculate the series for the change in net time for the class
*
* </pre>
*
* @author Michael Couck
* @since 12.06.10
* @version 01.00
*/
public class Profiler {
protected static Logger LOGGER = Logger.getLogger(Profiler.class);
public static void initialize(final IDataBase dataBase) {
long snapshptInterval = Configuration.getConfiguration().getSnapshotInterval();
LOGGER.info("Profiler initialize : " + dataBase + ", " + snapshptInterval);
if (snapshptInterval > 0) {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
try {
LOGGER.warn("Taking snapshot at : " + new Date());
new Snapshooter(null, dataBase).execute();
} catch (Exception e) {
LOGGER.error("Exception taking the snapshot : ", e);
}
}
};
timer.schedule(timerTask, snapshptInterval, snapshptInterval);
}
long reportInterval = Configuration.getConfiguration().getReportInterval();
LOGGER.info("Profiler initialize : " + dataBase + ", " + reportInterval);
if (reportInterval > 0) {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
try {
LOGGER.warn("Writing report at : " + new Date());
new Reporter(null, dataBase).execute();
} catch (Exception e) {
LOGGER.error("Exception taking the snapshot : ", e);
}
}
};
timer.schedule(timerTask, snapshptInterval, snapshptInterval);
}
}
/**
* Calculate the series for the total times for the method<br>
* methodSeries()<br>
* Snapshots {2, 5, 3, 6, 5}
*/
public static List<Long> methodSeries(Method<?, ?> method) {
List<Long> series = new ArrayList<Long>();
List<Snapshot<?, ?>> snapshots = method.getSnapshots();
for (Snapshot<?, ?> snapshot : snapshots) {
series.add(snapshot.getTotal());
}
return series;
}
/**
* Calculate the series for the net times for the method<br>
* methodNetSeries()<br>
* Snapshot {1, 2, 4, 3, 2}
*/
public static List<Long> methodNetSeries(Method<?, ?> method) {
List<Long> series = new ArrayList<Long>();
List<Snapshot<?, ?>> snapshots = method.getSnapshots();
for (Snapshot<?, ?> snapshot : snapshots) {
long netTime = snapshot.getTotal() - snapshot.getWait();
snapshot.setNet(netTime);
series.add(snapshot.getNet());
}
return series;
}
/**
* Calculate the total time for each method:<br>
* totalMethodTime()<br>
* Snapshots {2, 5, 3, 6, 5} = 2 + 5 + 3 + 6 + 5 = 21
*/
public static long totalMethodTime(Method<?, ?> method) {
List<Long> methodSeries = methodSeries(method);
long totalTime = 0;
for (Long time : methodSeries) {
totalTime += time;
}
return totalTime;
}
/**
* Calculate the total net time for each method<br>
* totalNetMethodTime()<br>
* Snapshot {1, 2, 4, 3, 2 } = 1 + 2 + 4 + 3 + 2 = 12
*/
public static long totalNetMethodTime(Method<?, ?> method) {
List<Long> methodNetSeries = methodNetSeries(method);
long totalNetTime = 0;
for (Long netTime : methodNetSeries) {
totalNetTime += netTime;
}
return totalNetTime;
}
/**
* Calculate the series for the change in total time for the method<br>
* methodChangeSeries()<br>
* Snapshots {2, 5, 3, 6, 5} = {3, -2, 3, -1}
*/
public static List<Long> methodChangeSeries(Method<?, ?> method) {
List<Long> series = new ArrayList<Long>();
List<Long> methodSeries = methodSeries(method);
long previousTime = 0;
for (Long time : methodSeries) {
long change = time - previousTime;
series.add(change);
previousTime = time;
}
return series;
}
/**
* Calculate the series for the change in net time for the method<br>
* methodNetChangeSeries()<br>
* Snapshot {1, 2, 4, 3, 2} = {1, 2, -1, -1}
*/
public static List<Long> methodNetChangeSeries(Method<?, ?> method) {
List<Long> series = new ArrayList<Long>();
List<Long> methodNetSeries = methodNetSeries(method);
long previousTime = 0;
for (Long time : methodNetSeries) {
long change = time - previousTime;
series.add(change);
previousTime = time;
}
return series;
}
/**
* Calculate the average total time for each method<br>
* averageMethodTime()<br>
* Snapshot {2, 5, 3, 6, 5} = (2 + 5 + 3 + 6 + 5)/5 = 21/5 = 4.2
*/
public static long averageMethodTime(Method<?, ?> method) {
List<Long> methodSeries = methodSeries(method);
long totalTime = 0;
for (Long time : methodSeries) {
totalTime += time;
}
long denominator = methodSeries.size() > 0 ? methodSeries.size() : 1;
return totalTime / denominator;
}
/**
* Calculate the average net time for each method<br>
* averageMethodNetTime()<br>
* Snapshot {1, 2, 4, 3, 2} = (1 + 2 + 4 + 3 + 2)/5 = 12/5 = 2.4
*/
public static long averageMethodNetTime(Method<?, ?> method) {
List<Long> methodNetSeries = methodNetSeries(method);
long totalTime = 0;
for (Long time : methodNetSeries) {
totalTime += time;
}
long denominator = methodNetSeries.size() > 0 ? methodNetSeries.size() : 1;
return totalTime / denominator;
}
/**
* Calculate the total change for the methods<br>
* methodChange()<br>
* Snapshots {2, 5, 3, 6, 5} = 3
*/
public static long methodChange(Method<?, ?> method) {
List<Long> methodSeries = methodSeries(method);
long totalChange = 0;
long previousTime = 0;
for (Long time : methodSeries) {
long change = time - previousTime;
totalChange += change;
previousTime = time;
}
return totalChange;
}
/**
* Calculate the net change for the methods<br>
* methodNetChange()<br>
* Snapshot {1, 2, 4, 3, 2} = 1
*/
public static long methodNetChange(Method<?, ?> method) {
List<Long> methodNetSeries = methodNetSeries(method);
long totalChange = 0;
long previousTime = 0;
for (Long time : methodNetSeries) {
long change = time - previousTime;
totalChange += change;
previousTime = time;
}
return totalChange;
}
}