Method.java
Home
/
src /
main /
java /
br /
ufrgs /
inf /
prosoft /
memoizeit /
Method.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package br.ufrgs.inf.prosoft.memoizeit;
import br.ufrgs.inf.prosoft.memoizeit.cache.CachingPerformance;
import br.ufrgs.inf.prosoft.memoizeit.cache.MultiCache;
import br.ufrgs.inf.prosoft.memoizeit.cache.SingleCache;
import br.ufrgs.inf.prosoft.memoizeit.graph.Node;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author romulo
*/
public class Method {
private static final Logger logger = Logger.getLogger(Method.class.getName());
private final String name;
private final List<Occurrence> occurrences;
private double representativeness;
private Map<String, List<Occurrence>> groupByParameter;
private Boolean fullyExplored;
private final boolean isStatic;
public Method(String name, boolean isStatic, List<Occurrence> occurrences) {
this.name = name;
this.occurrences = occurrences;
this.fullyExplored = false;
this.isStatic = isStatic;
}
public String getName() {
return name;
}
public int getOccurrencesSize() {
return this.occurrences.size();
}
public void setRepresentativeness(double representativeness) {
this.representativeness = representativeness;
}
public double getRepresentativeness() {
return representativeness;
}
public int getDistinctOccurrencesSize() {
return this.groupByParameter.size();
}
public long getTotalExecutionTime() {
return this.occurrences.stream()
.map(Occurrence::getExecutionTime)
.reduce(Long::sum).get();
}
public long getAverageExecutionTime() {
return getTotalExecutionTime() / this.occurrences.size();
}
public double getSavedTime() {
return getAverageExecutionTime() * getPotentialHitRatio();
}
protected boolean wasFullyExplored() {
return this.fullyExplored;
}
protected void groupByParameter(int depth) {
logger.log(Level.INFO, "Grouping by parameters {0} occurrences of {1}", new Object[]{this.name, this.occurrences.size()});
this.groupByParameter = new HashMap<>();
this.occurrences.stream().parallel().forEach(new Consumer<Occurrence>() {
int i = 0;
@Override
public void accept(Occurrence occurrence) {
System.out.print(".");
System.out.flush();
if (++i % 100 == 0) {
System.out.println();
}
if (depth < Integer.MAX_VALUE) {
OccurrenceConcrete thisOccurrence = occurrence.getConcrete();
OccurrenceConcrete truncated = thisOccurrence.getView(depth);
Method.this.fullyExplored = truncated == thisOccurrence;
occurrence = truncated;
}
String parameters = occurrence.getParameters().toString();
synchronized (Method.this.groupByParameter) {
try {
Method.this.groupByParameter.get(parameters).add(occurrence);
} catch (Exception e) {
List<Occurrence> occurrences = new ArrayList<>();
occurrences.add(occurrence);
Method.this.groupByParameter.put(parameters, occurrences);
}
}
}
});
}
protected void groupByParameter() {
groupByParameter(Integer.MAX_VALUE);
}
protected boolean isChangeful() {
for (Map.Entry<String, List<Occurrence>> entry : this.groupByParameter.entrySet()) {
if (entry.getValue().size() == 1) {
continue;
}
Occurrence firstOccurrence = entry.getValue().get(0);
if (entry.getValue().stream()
.anyMatch(occurrence -> occurrence.getReturnValue() != null
&& !occurrence.getReturnValue().equals(firstOccurrence.getReturnValue()))) {
return true;
}
}
return false;
}
protected double getPotentialHitRatio() {
double potentialHitRatio = this.groupByParameter.entrySet().stream().map(entry -> entry.getValue().size()).reduce(Integer::sum).get();
potentialHitRatio = (potentialHitRatio - this.groupByParameter.size()) / potentialHitRatio;
return potentialHitRatio;
}
protected void removeUnusedFields(Node<String> methodNode) {
logger.log(Level.INFO, "Removing unused fields of {0} occurrences of {1}", new Object[]{this.occurrences.size(), this.name});
if (methodNode == null) {
logger.log(Level.WARNING, "methodNode null: {0}", this.name);
return;
}
this.occurrences.stream().parallel()
.forEach(new Consumer<Occurrence>() {
private int i = 1;
@Override
public void accept(Occurrence occurrence) {
System.out.print(".");
if (i++ % 100 == 0) {
System.out.println();
}
occurrence.removeUnusedFields(methodNode);
}
});
System.out.println();
}
protected Map<String, CachingPerformance> simulateCachingStrategies() {
Map<String, CachingPerformance> cachingStrategyHasPerformance = new HashMap<>();
CachingPerformance globalMultiCachePerformance = new CachingPerformance();
CachingPerformance globalSingleCachePerformance = new CachingPerformance();
CachingPerformance instanceMultiCachePerformance = new CachingPerformance();
CachingPerformance instanceSingleCachePerformance = new CachingPerformance();
cachingStrategyHasPerformance.put("globalMultiCache", globalMultiCachePerformance);
cachingStrategyHasPerformance.put("globalSingleCache", globalSingleCachePerformance);
cachingStrategyHasPerformance.put("instanceMultiCache", instanceMultiCachePerformance);
cachingStrategyHasPerformance.put("instanceSingleCache", instanceSingleCachePerformance);
MultiCache globalMultiCache = new MultiCache(globalMultiCachePerformance);
SingleCache globalSingleCache = new SingleCache(globalSingleCachePerformance);
Map<String, MultiCache> instanceHasMultiCache = new HashMap<>();
Map<String, SingleCache> instanceHasSingleCache = new HashMap<>();
for (Occurrence occurrence : this.occurrences) {
if (!this.isStatic) {
MultiCache instanceMultiCache = instanceHasMultiCache.get(occurrence.getInstance());
if (instanceMultiCache == null) {
instanceMultiCache = new MultiCache(instanceMultiCachePerformance);
instanceHasMultiCache.put(occurrence.getInstance(), instanceMultiCache);
}
occurrence.simulateCaching(instanceMultiCache);
SingleCache instanceSingleCache = instanceHasSingleCache.get(occurrence.getInstance());
if (instanceSingleCache == null) {
instanceSingleCache = new SingleCache(instanceSingleCachePerformance);
instanceHasSingleCache.put(occurrence.getInstance(), instanceSingleCache);
}
occurrence.simulateCaching(instanceSingleCache);
}
occurrence.simulateCaching(globalMultiCache);
occurrence.simulateCaching(globalSingleCache);
}
return cachingStrategyHasPerformance;
}
@Override
public int hashCode() {
int hash = 5;
hash = 37 * hash + Objects.hashCode(this.name);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Method)) {
return false;
}
Method method = (Method) obj;
return this.name.equals(method.name);
}
@Override
public String toString() {
return this.name;
}
}