package de.gaalop.gapp.statistics;
import de.gaalop.cfg.ControlFlowGraph;
import de.gaalop.gapp.PairSetOfVariablesAndIndices;
import de.gaalop.gapp.SetVectorArgument;
import de.gaalop.gapp.instructionSet.GAPPAssignInputsVector;
import de.gaalop.gapp.instructionSet.GAPPAssignMv;
import de.gaalop.gapp.instructionSet.GAPPCalculateMv;
import de.gaalop.gapp.instructionSet.GAPPCalculateMvCoeff;
import de.gaalop.gapp.instructionSet.GAPPDotVectors;
import de.gaalop.gapp.instructionSet.GAPPResetMv;
import de.gaalop.gapp.instructionSet.GAPPSetMv;
import de.gaalop.gapp.instructionSet.GAPPSetVector;
import de.gaalop.gapp.variables.GAPPMultivector;
import de.gaalop.gapp.variables.GAPPSetOfVariables;
import de.gaalop.gapp.visitor.CFGGAPPVisitor;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
/**
* GAPP Visitor which shows the maximum memory usage in program
* @author Christian Steinmetz
*/
public class MemoryUsage extends CFGGAPPVisitor {
private HashMap<String, LiveStatistics> liveStatistics = new HashMap<String, LiveStatistics>();
private int curLine = 0;
private MemoryUsage() { //Make usage of static method mandatory
}
/**
* Prints the memory usage of a control flow graph
* @param graph The graph
*/
public static void printMemoryUsage(ControlFlowGraph graph) {
MemoryUsage visitor = new MemoryUsage();
graph.accept(visitor);
System.out.println("#Instructions: " + visitor.curLine);
System.out.println("#Multivectors: " + visitor.liveStatistics.size());
long sum = 0;
for (LiveStatistics live : visitor.liveStatistics.values()) {
sum += live.getSize();
}
System.out.println("Sum of multivectors sizes (liveness start until end): " + sum);
System.out.println("Maximum of used space: " + visitor.maximumUsedSpace());
}
/**
* Returns the maximum used space
* @return The maximum used space
*/
private long maximumUsedSpace() {
// Divide and Conquer algorithm start
return maximumUsedSpaceDivAndConq(1, curLine, liveStatistics.values());
}
/**
* Returns the maximum used space of an interval
* @param lineStart The interval start
* @param lineEnd The interval end
* @param list The list of LiveStatistics that overlap with the interval
* @return The maximum used space of the interval
*/
private long maximumUsedSpaceDivAndConq(int lineStart, int lineEnd, Collection<LiveStatistics> list) {
if (list.isEmpty()) {
return 0;
}
if (lineEnd - lineStart == 0) {
//simple case
long sum = 0;
for (LiveStatistics stat : list) {
sum += stat.getSize();
}
return sum;
} else {
//difficult case: split to simpler cases
//create the separated lists
int centerlastIntLeft = (lineStart + lineEnd) / 2;
LinkedList<LiveStatistics> leftList = new LinkedList<LiveStatistics>();
LinkedList<LiveStatistics> rightList = new LinkedList<LiveStatistics>();
for (LiveStatistics element : list) {
Interval interval = element.getInterval();
int from = interval.getFrom();
int to = interval.getTo();
if (from <= centerlastIntLeft) {
leftList.add(element);
if (to > centerlastIntLeft) {
rightList.add(element);
}
} else {
rightList.add(element);
}
}
// recursion
long leftMax = maximumUsedSpaceDivAndConq(lineStart, centerlastIntLeft, leftList);
long rightMax = maximumUsedSpaceDivAndConq(centerlastIntLeft + 1, lineEnd, rightList);
// merge
return Math.max(leftMax, rightMax);
}
}
/**
* This method is called, if a GAPPSetOfVariables instance is accessed
* @param gappSetOfVariables The GAPPSetOfVariables instance
*/
private void access(GAPPSetOfVariables gappSetOfVariables) {
if (!liveStatistics.containsKey(gappSetOfVariables.getName())) {
System.err.println("Multivector " + gappSetOfVariables.getName() + " was not reseted!");
} else {
liveStatistics.get(gappSetOfVariables.getName()).getInterval().setTo(curLine);
}
}
@Override
public Object visitAssignMv(GAPPAssignMv gappAssignMv, Object arg) {
curLine++;
access(gappAssignMv.getDestination());
return null;
}
@Override
public Object visitDotVectors(GAPPDotVectors gappDotVectors, Object arg) {
curLine++;
access(gappDotVectors.getDestination());
return null;
}
@Override
public Object visitResetMv(GAPPResetMv gappResetMv, Object arg) {
curLine++;
liveStatistics.put(gappResetMv.getDestination().getName(),
new LiveStatistics(curLine, gappResetMv.getSize()));
return null;
}
@Override
public Object visitSetMv(GAPPSetMv gappSetMv, Object arg) {
curLine++;
access(gappSetMv.getDestination());
access(gappSetMv.getSource());
return null;
}
@Override
public Object visitSetVector(GAPPSetVector gappSetVector, Object arg) {
curLine++;
for (SetVectorArgument curArg: gappSetVector.getEntries())
if (!curArg.isConstant()) {
PairSetOfVariablesAndIndices p = (PairSetOfVariablesAndIndices) curArg;
access(p.getSetOfVariable());
}
return null;
}
@Override
public Object visitCalculateMv(GAPPCalculateMv gappCalculateMv, Object arg) {
curLine++;
access(gappCalculateMv.getDestination());
access(gappCalculateMv.getOperand1());
if (gappCalculateMv.getOperand2() != null) {
access(gappCalculateMv.getOperand2());
}
return null;
}
@Override
public Object visitCalculateMvCoeff(GAPPCalculateMvCoeff gappCalculateMvCoeff, Object arg) {
curLine++;
access(new GAPPMultivector(gappCalculateMvCoeff.getDestination().getName()));
access(gappCalculateMvCoeff.getOperand1());
if (gappCalculateMvCoeff.getOperand2() != null) {
access(gappCalculateMvCoeff.getOperand2());
}
return null;
}
@Override
public Object visitAssignInputsVector(GAPPAssignInputsVector gAPPAssignInputsVector, Object arg) {
curLine++;
access(new GAPPMultivector("inputsVector"));
return null;
}
}