package fr.lifl.stc.stan.analyser;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.JavaClass;
/**
* Class used to compute different statistics
*
* @author dorina
*
*/
public class Stats {
public static PrintWriter printerStats;
//current iteration on a set of classes
static int currIteration = -1;
/**
* number of times global signatures are used for invoke
bytecodes
* insted of exact signatures
*/
public static long noGlobalInvoke;
/**
* number of times exact signatures are used for invoke
bytecodes
*/
public static long noExactInvoke;
/**
* statistics variables
*/
static int maxPass = 0, minPass = 1000, noLabels = 0, noMethods = 0;
static long noPass = 0;
static float moyenne = 2.43f;
static float noPassDiff;
static Hashtable noMethodsPerPass;
static Hashtable noLabelsPerMethod;
//////////////////////////////////////////////////
//// Stats for each iteration on a set of classes
//////////////////////////////////////////////////
static final int MAX_ITERATIONS = 15;
// int (iteration id) => int (number of analyzed methods)
//static int methPerIteration[] = new int[MAX_ITERATIONS];
static Vector methPerIteration = new Vector();
// long (time) for each iteration
//static long timePerIteration[] = new long[MAX_ITERATIONS];
static Vector timePerIteration = new Vector();
/**
* the total size of the proof loaded with the code
*/
static int sizeOfProof;
static long startTime;
public static void initIteration() {
noGlobalInvoke = 0;
noExactInvoke = 0;
maxPass = 0;
minPass = 10000;
noLabels = 0;
noMethods = 0;
noPass = 0;
noPassDiff = 0.0f;
noMethodsPerPass = new Hashtable();
noLabelsPerMethod = new Hashtable();
currIteration ++;
//methPerIteration[currIteration] = 0;
//methPerIteration.setElementAt(new Integer(0), currIteration);
methPerIteration.add(new Integer(0));
sizeOfProof = 0;
startTime = System.currentTimeMillis();
}
public static void endIteration(){
//timePerIteration[currIteration] = System.currentTimeMillis() - startTime;
timePerIteration.add(new Long(System.currentTimeMillis() - startTime));
}
static void incAnalyzedMethod(){
int i = methPerIteration.elementAt(currIteration).intValue();
methPerIteration.setElementAt(new Integer(i+1), currIteration);
//methPerIteration[currIteration]++;
}
static void registerLargeMethod(JavaClass cls, Method method, long time) {
if(Config.statisticsEnabled()) {
try {
printerStats = new PrintWriter(new FileWriter(Config.statisticsFile()+".tmp", true));
printerStats.println("iteration "+currIteration+": "+cls.getClassName()+"."+method.getName()+method.getSignature()+" : time : "+time);
printerStats.close();
}
catch(IOException e) {
System.out.println("Exception: "+ e);
}
}
}
public static void stats(MethodAnalyzer m) {
Hashtable h = m.statsLabels;
noLabels += h.size();
noMethods++;
Integer tmpSize = new Integer(h.size());
if (noLabelsPerMethod.containsKey(tmpSize)) {
int i = noLabelsPerMethod.get(tmpSize).intValue();
noLabelsPerMethod.put(tmpSize, new Integer(i + 1));
} else
noLabelsPerMethod.put(tmpSize, new Integer(1));
Iterator it = h.keySet().iterator();
int maxLocal = 0;
while (it.hasNext()) {
int x = h.get(it.next()).intValue();
if (x > 0) {
noPassDiff += Math.abs(moyenne - (float) x);
}
noPass += x;
// if (x == 49)
// System.out.println("methode name = " + m.getJavaClass().getClassName()
// + "." + m.getMethod().getName() + m.getMethod().getSignature());
if (x > maxPass)
maxPass = x;
if (x > maxLocal)
maxLocal = x;
if (x < minPass)
minPass = x;
}
Integer maxi = new Integer(maxLocal);
if (noMethodsPerPass.containsKey(maxi)) {
int i = noMethodsPerPass.get(maxi).intValue();
noMethodsPerPass.put(maxi, new Integer(i + 1));
} else
noMethodsPerPass.put(maxi, new Integer(1));
}
public static void printStats() {
String s = "";
s += "\r\n no methods:\t " + noMethods;
s += "\r\n no labels:\t " + noLabels;
s += "\r\n no pass:\t " + noPass;
s += "\r\n no pass/label:\t " + ((double) noPass)
/ (double) noLabels;
s += "\r\n no pass diff:\t " + noPassDiff;
s += "\r\n no pass diff/label:\t " + (noPassDiff)
/ (float) noLabels;
s += "\r\n pass max:\t " + maxPass;
s += "\r\n pass min:\t " + minPass;
s += "\r\n\r\nNo methods per pass (no pass: no methods):\r\n";
Object[] arr = noMethodsPerPass.keySet().toArray();
Arrays.sort(arr);
for (int i = 0; i < arr.length; i++) {
Integer key = (Integer) arr[i];
int val = noMethodsPerPass.get(key).intValue();
s += "\r\n "+key.intValue() + ":\t" + val;
}
s+="\r\n\r\nNo Labels per method (no labels: no methods):\r\n";
arr = noLabelsPerMethod.keySet().toArray();
Arrays.sort(arr);
for (int i = 0; i < arr.length; i++) {
Integer key = (Integer) arr[i];
int val = noLabelsPerMethod.get(key).intValue();
s += "\r\n "+key.intValue() + ":\t" + val;
}
s += "\r\nNo global signature used : " + noGlobalInvoke;
s += "\r\nNo exact signature used : " + noExactInvoke;
////////////////////////////////////////
//stats regarding no of analyzed methods
////////////////////////////////////////
s += "\r\n\r\n For each iteration, number of analyzed methods (methods not final):";
for(int i = 0; i <= currIteration; i++)
s += "\r\n Iteration "+i+" = "+methPerIteration.elementAt(i)+" methods";
s += "\r\n\r\n For each iteration, time (miliseconds):";
for(int i = 0; i <= currIteration; i++)
s += "\r\n Iteration "+i+" = "+timePerIteration.elementAt(i)+" ms";
println(s);
}
public static void print(String s){
if(Config.statisticsEnabled()) {
try {
printerStats = new PrintWriter(new FileWriter(Config.statisticsFile(), true));
printerStats.print(s);
printerStats.close();
}
catch(IOException e) {
System.out.println("Exception: "+ e);
}
}
}
public static void println(String s){
if(Config.statisticsEnabled()) {
try {
printerStats = new PrintWriter(new FileWriter(Config.statisticsFile(), true));
printerStats.println(s);
printerStats.close();
}
catch(IOException e) {
System.out.println("Exception: "+ e);
}
}
}
public static String statsToString(MethodAnalyzer m) {
Hashtable h = m.statsLabels;
String s = "" + h.size() + " : ";
Iterator it = h.keySet().iterator();
while (it.hasNext()) {
int x = h.get(it.next()).intValue();
s += x + ";";
}
return s;//+"\n";
}
//stats memory
static long min = 100000000;
static long max = 0;
static int noMeth = 0;
static long totalMem = 0;
public static void addMemory(long m){
if(mmax)
max = m;
totalMem += m;
noMeth++;
}
public static void printMemory(){
// System.out.println("min memory = "+min);
// System.out.println("max memory = "+max);
// System.out.println("total memory = "+totalMem);
// System.out.println("average memory = "+totalMem/noMeth);
System.out.println("max aprox memory online = "+maxOnLine/1024f);
System.out.println("max aprox memory offline = "+maxOffLine/1024f);
System.out.println("avg aprox memory online = "+totalOnLine/countMem/1024f);
System.out.println("avg aprox memory offline = "+totalOffLine/countMem/1024f);
}
//stats memory; aproximation
static long maxOnLine = 0;
static long maxOffLine = 0;
static int countMem = 0;
static long totalOnLine =0;
static long totalOffLine =0;
public static void aproxMemory(int noLabels, int sizeTableLink){
long online = 2*sizeTableLink*sizeTableLink+sizeTableLink*10;
maxOnLine = Math.max(maxOnLine, online);
totalOnLine += online;
long offline = 4*noLabels*sizeTableLink*sizeTableLink+sizeTableLink*22;
maxOffLine = Math.max(maxOffLine, offline);
totalOffLine += offline;
countMem++;
}
}