Method.java
Home
/
src /
main /
java /
br /
ufrgs /
inf /
prosoft /
aplcachetf /
extension /
metadata /
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.aplcachetf.extension.metadata;
import br.ufrgs.inf.prosoft.aplcachetf.extension.metrics.CacheabilityPatternDecider;
import br.ufrgs.inf.prosoft.tfcache.Metrics;
import br.ufrgs.inf.prosoft.tfcache.StorageManager;
import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
import br.ufrgs.inf.prosoft.tfcache.metadata.Occurrence;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
*
* @author root
*/
public class Method {
private static final Logger LOGGER = Logger.getLogger(Method.class.getName());
private final String name;
private List<Occurrence> occurrences;
private List<GroupOfOccurrences> groupsOfOccurrences;
private Metrics bestMetrics;
public Method(String name, List<Occurrence> occurrences) {
this.name = name;
if (occurrences == null) {
throw new RuntimeException("Occurrences is null");
}
if (occurrences.isEmpty()) {
throw new RuntimeException("Occurrences is empty");
}
this.occurrences = occurrences;
}
public String getName() {
return this.name;
}
public Metrics getBestMetrics() {
return this.bestMetrics;
}
public long getEstimatedSavedTime() {
if (getBestMetrics() != null) {
return getBestMetrics().getSavedTime();
}
return groupsOfOccurrences().map(group -> group.getSavedTime()).reduce(Long::sum).orElse(0L);
}
public BigDecimal getEstimatedSavedTimePerTimeInCache() {
if (getBestMetrics() != null) {
return getBestMetrics().getSavedTimePerTimeInCache();
}
GroupOfOccurrences max = groupsOfOccurrences().max(Comparator.comparing(GroupOfOccurrences::getSavedTimePerTimeInCache)).get();
return max.getSavedTimePerTimeInCache();
}
public Stream<Occurrence> occurrences() {
return this.occurrences.stream();
}
public Stream<GroupOfOccurrences> groupsOfOccurrences() {
if (this.groupsOfOccurrences == null) {
groupByInput();
}
return this.groupsOfOccurrences.stream();
}
public int getOccurrencesSize() {
return this.occurrences.size();
}
private void groupByInput() {
Map<String, List<Occurrence>> inputHasOccurrences = new ConcurrentHashMap<>();
occurrences().forEach(occurrence -> {
String parameters = occurrence.getParametersSerialised();
inputHasOccurrences.compute(parameters, (key, oldValue) -> {
if (oldValue == null) {
oldValue = new ArrayList<>();
}
oldValue.add(occurrence);
return oldValue;
});
});
this.groupsOfOccurrences = inputHasOccurrences.entrySet().stream()
.map(entry -> new GroupOfOccurrences(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
public void removeSingleOccurrences() {
if (this.groupsOfOccurrences == null) {
groupByInput();
}
int initialCountofOccurrences = this.groupsOfOccurrences.size();
this.groupsOfOccurrences.removeIf(groupOfOccurrences -> groupOfOccurrences.getOccurrencesSize() < 2);
int removedOccurrences = initialCountofOccurrences - this.groupsOfOccurrences.size();
if (removedOccurrences > 0) {
LOGGER.log(Level.INFO, "\tRemoved {0} of {1} inputs from method {2}", new Object[]{removedOccurrences, initialCountofOccurrences, this.name});
}
}
public void calculateMetrics() {
if (this.groupsOfOccurrences == null) {
groupByInput();
}
groupsOfOccurrences().forEach(GroupOfOccurrences::calculateMetrics);
String uuid = Configuration.getUUID().replace("level:input", "level:method");
Metrics metrics = StorageManager.get(uuid, this.occurrences);
if (this.bestMetrics == null && metrics != null) {
this.bestMetrics = metrics;
}
}
public void calculateThresholds() {
this.groupsOfOccurrences.stream().forEach(GroupOfOccurrences::calculateThresholds);
}
public void filterCacheableInputs() {
int initialInputsSize = this.groupsOfOccurrences.size();
this.groupsOfOccurrences.removeIf(CacheabilityPatternDecider::isNotCacheable);
int removedInputs = initialInputsSize - this.groupsOfOccurrences.size();
if (removedInputs > 0) {
LOGGER.log(Level.INFO, "\tRemoved {0} of {1} uncacheable inputs from method {2}", new Object[]{removedInputs, initialInputsSize, this.name});
}
initialInputsSize = this.groupsOfOccurrences.size();
this.groupsOfOccurrences.removeIf(groupOfOccurrence -> groupOfOccurrence.getTtl() == 0);
removedInputs = initialInputsSize - this.groupsOfOccurrences.size();
if (removedInputs > 0) {
LOGGER.log(Level.INFO, "\tRemoved {0} of {1} inputs with 0 TTL from method {2}", new Object[]{removedInputs, initialInputsSize, this.name});
}
}
@Override
public String toString() {
return this.name;
}
}