adaptive-caching-framework
Changes
evaluation/applications/AP/spring-petclinic/src/main/java/org/springframework/samples/petclinic/Configuration.java 2(+2 -0)
framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/analysis/Analyzer.java 3(+1 -2)
framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/configuration/annotation/AdaptiveCaching.java 4(+2 -2)
framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/monitoring/application/aspects/TracerAspect.java 18(+12 -6)
framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/annotations/Criteria.java 22(+22 -0)
framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightAnalyzer.java 116(+116 -0)
framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightMetricAspect.java 131(+112 -19)
framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightMetrics.java 142(+123 -19)
framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/StaticMetrics.java 58(+58 -0)
framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/statistics/StatisticalTest.java 16(+6 -10)
framework/autonomicmanager/src/test/java/br/ufrgs/inf/prosoft/adaptivecaching/analysis/decision/flowchart/Populator.java 6(+0 -6)
Details
diff --git a/evaluation/applications/AP/spring-petclinic/src/main/java/org/springframework/samples/petclinic/Configuration.java b/evaluation/applications/AP/spring-petclinic/src/main/java/org/springframework/samples/petclinic/Configuration.java
index 082f6a4..eaec9c8 100644
--- a/evaluation/applications/AP/spring-petclinic/src/main/java/org/springframework/samples/petclinic/Configuration.java
+++ b/evaluation/applications/AP/spring-petclinic/src/main/java/org/springframework/samples/petclinic/Configuration.java
@@ -5,11 +5,13 @@ import br.ufrgs.inf.prosoft.adaptivecaching.configuration.annotation.ComponentSc
import br.ufrgs.inf.prosoft.adaptivecaching.configuration.annotation.types.CacheProviderType;
import br.ufrgs.inf.prosoft.adaptivecaching.configuration.annotation.types.Modelling;
import br.ufrgs.inf.prosoft.adaptivecaching.configuration.annotation.types.RepositoryType;
+import br.ufrgs.inf.prosoft.adaptivecaching.sampling.annotations.Criteria;
@AdaptiveCaching(cacheProvider = CacheProviderType.EHCACHE, logRepository = RepositoryType.MEMORY,
modelling = Modelling.FULLEXPLORATION, analyzerEnabled = true, enabled = true, disableMonitoringAfterAnalysis = true,
clearMonitoringDataOnStart = true, traceAsync = false, tracerEnabled = true, analyzeOnce = true, expiryInterval = 60)
+@Criteria("more frequent I more expensive")
//Jhonny: workaround below. a better solution involve filter by serialization methods in aspect to avoid it
@ComponentScan(allowed = "org.springframework.samples.petclinic", denied = "org.springframework.samples.petclinic.model")
public class Configuration {
diff --git a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/analysis/Analyzer.java b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/analysis/Analyzer.java
index bb58a2b..36b87a7 100644
--- a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/analysis/Analyzer.java
+++ b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/analysis/Analyzer.java
@@ -18,6 +18,7 @@ import br.ufrgs.inf.prosoft.adaptivecaching.monitoring.cache.CacheMonitor;
import br.ufrgs.inf.prosoft.adaptivecaching.monitoring.cache.vendors.guava.GuavaMonitor;
import br.ufrgs.inf.prosoft.adaptivecaching.monitoring.storage.providers.MongoRepository;
import br.ufrgs.inf.prosoft.adaptivecaching.monitoring.storage.Repository;
+import br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics.LightweightAnalyzer;
import br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics.LightweightMetricAspect;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
@@ -56,8 +57,6 @@ public class Analyzer implements Runnable {
@Override
public void run() {
- logger.info("LightweightMetricAspect.metrics: {}", LightweightMetricAspect.metrics);
-
if (!TracerAspect.analyzerEnabled) {
logger.info("Analyzer disabled, not running...");
return;
diff --git a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/configuration/annotation/AdaptiveCaching.java b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/configuration/annotation/AdaptiveCaching.java
index 339e18a..d113d49 100644
--- a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/configuration/annotation/AdaptiveCaching.java
+++ b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/configuration/annotation/AdaptiveCaching.java
@@ -27,8 +27,8 @@ public @interface AdaptiveCaching {
@Deprecated long firstExpiry() default 300000; //5 minutes
//todo when analysis based on trigger do not make sense to have this, its similar to trigger by time
- @Deprecated long analysisInterval() default 300000; //5 minutes
- @Deprecated long firstAnalysis() default 120000; //2 minutes
+ @Deprecated long analysisInterval() default 600000; //10 minutes
+ @Deprecated long firstAnalysis() default 240000; //4 minutes
TriggerType triggerType() default TriggerType.TIME; //if were not by time, load the class that implements the interface @Trigger
diff --git a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/monitoring/application/aspects/TracerAspect.java b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/monitoring/application/aspects/TracerAspect.java
index fdb22db..49bef4a 100644
--- a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/monitoring/application/aspects/TracerAspect.java
+++ b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/monitoring/application/aspects/TracerAspect.java
@@ -19,6 +19,8 @@ import br.ufrgs.inf.prosoft.adaptivecaching.monitoring.cache.CacheMonitorFactory
import br.ufrgs.inf.prosoft.adaptivecaching.monitoring.storage.Repository;
import br.ufrgs.inf.prosoft.adaptivecaching.monitoring.storage.RepositoryFactory;
import br.ufrgs.inf.prosoft.adaptivecaching.monitoring.storage.providers.MongoRepository;
+import br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics.LightweightAnalyzer;
+import br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics.LightweightMetricAspect;
import com.mongodb.MongoClient;
import com.mongodb.MongoTimeoutException;
import com.mongodb.client.MongoDatabase;
@@ -181,7 +183,6 @@ public class TracerAspect {
if (cachingConfig.analyzerEnabled()) {
TracerAspect.analyzerEnabled = true;
//TODO trigger by time
- //maybe we should kill it or delete the object?
analyzerExecutor.scheduleWithFixedDelay(
new Analyzer(repository, cacheMonitor.getCacheInfo(), cachingConfig),
cachingConfig.firstAnalysis(), cachingConfig.analysisInterval(), TimeUnit.MILLISECONDS);
@@ -254,11 +255,16 @@ public class TracerAspect {
}
//trace only allowed packages
- for (String p : allowed) {
- if (joinPoint.getSignature().toLongString().contains(p)
- && !methodBlackList.contains(joinPoint.getSignature().toLongString()))
- return true;
- }
+// for (String p : allowed) {
+// if (joinPoint.getSignature().toLongString().contains(p)
+// && !methodBlackList.contains(joinPoint.getSignature().toLongString()))
+// return true;
+// }
+
+ //trace only allowed by lightweight metrics
+ if (LightweightAnalyzer.allowedFineGrained
+ .contains(joinPoint.getSignature().toLongString()))
+ return true;
return false;
}
diff --git a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/annotations/Criteria.java b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/annotations/Criteria.java
new file mode 100644
index 0000000..446fe41
--- /dev/null
+++ b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/annotations/Criteria.java
@@ -0,0 +1,22 @@
+package br.ufrgs.inf.prosoft.adaptivecaching.sampling.annotations;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Documented
+public @interface Criteria {
+
+ /**
+ * Criteria in form of SET operations over the criteria.
+ *
+ * Operations allowed: union (U), intersection (I), difference (D), complement (C)
+ * Verbs: frequent, expensive, changeable, errorprone, globalimpact
+ * Additional: more, less
+ *
+ * Examples:
+ * more frequent U more expensive C less changeable
+ * less frequent C less expensive
+ */
+ String value() default "";
+}
diff --git a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightAnalyzer.java b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightAnalyzer.java
new file mode 100644
index 0000000..9612e1d
--- /dev/null
+++ b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightAnalyzer.java
@@ -0,0 +1,116 @@
+package br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics;
+
+import br.ufrgs.inf.prosoft.adaptivecaching.sampling.statistics.StatisticalTest;
+import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class LightweightAnalyzer implements Runnable {
+
+ static Logger logger = LoggerFactory.getLogger(LightweightAnalyzer.class);
+
+ public static Set<String> allowedFineGrained = new HashSet<>();
+
+ public static void analyze() {
+
+ logger.info("Analyzing {} lightweight methods for relevance", LightweightMetricAspect.metrics.size());
+
+ DescriptiveStatistics frequencies = new DescriptiveStatistics();
+ DescriptiveStatistics changeabilities = new DescriptiveStatistics();
+ DescriptiveStatistics errorprones = new DescriptiveStatistics();
+ DescriptiveStatistics latencies = new DescriptiveStatistics();
+ DescriptiveStatistics maintainabilities = new DescriptiveStatistics();
+ DescriptiveStatistics userBehaviors = new DescriptiveStatistics();
+ DescriptiveStatistics concurrencies = new DescriptiveStatistics();
+ DescriptiveStatistics expensiveness = new DescriptiveStatistics();
+ DescriptiveStatistics globalimpact = new DescriptiveStatistics();
+ for (String method : LightweightMetricAspect.metrics.keySet()) {
+ LightweightMetrics sc = LightweightMetricAspect.metrics.get(method);
+ frequencies.addValue(sc.getFrequency());
+ changeabilities.addValue(sc.getChangeability());
+ errorprones.addValue(sc.getStaticErrorprone());
+ latencies.addValue(sc.getLatency());
+ maintainabilities.addValue(sc.getMaintainability());
+ userBehaviors.addValue(sc.getUserBehavior());
+ concurrencies.addValue(sc.getConcurrency());
+ expensiveness.addValue(sc.getExpensiveness());
+ globalimpact.addValue(sc.getGlobalImpact());
+
+// System.out.print(sc.getFrequency() + ",");
+ }
+
+ System.out.println("---------------------------");
+ System.out.println("Metric: frequency; Distribution: " +
+ ((StatisticalTest.isNormalDistribution(frequencies.getValues(), 0.05)) ? "normal" : "not_normal"));
+ System.out.println("Metric: maintainability; Distribution: " +
+ ((StatisticalTest.isNormalDistribution(maintainabilities.getValues(), 0.05)) ? "normal" : "not_normal"));
+ System.out.println("Metric: changeability; Distribution: " +
+ ((StatisticalTest.isNormalDistribution(changeabilities.getValues(), 0.05)) ? "normal" : "not_normal"));
+ System.out.println("Metric: userBehavior; Distribution: " +
+ ((StatisticalTest.isNormalDistribution(userBehaviors.getValues(), 0.05)) ? "normal" : "not_normal"));
+ System.out.println("Metric: concurrency; Distribution: " +
+ ((StatisticalTest.isNormalDistribution(concurrencies.getValues(), 0.05)) ? "normal" : "not_normal"));
+ System.out.println("Metric: errorprone; Distribution: " +
+ ((StatisticalTest.isNormalDistribution(errorprones.getValues(), 0.05)) ? "normal" : "not_normal"));
+ System.out.println("Metric: expensiveness; Distribution: " +
+ ((StatisticalTest.isNormalDistribution(expensiveness.getValues(), 0.05)) ? "normal" : "not_normal"));
+ System.out.println("Metric: globalimpact; Distribution: " +
+ ((StatisticalTest.isNormalDistribution(globalimpact.getValues(), 0.05)) ? "normal" : "not_normal"));
+ System.out.println("Metric: latency; Distribution: " +
+ ((StatisticalTest.isNormalDistribution(latencies.getValues(), 0.05)) ? "normal" : "not_normal"));
+
+ //cleaning selected methods
+ allowedFineGrained = new HashSet<>();
+
+ //TODO precess SET operations dynamically
+// LightweightMetricAspect.criteriaDSL
+
+// //Example: more frequent I more expensive
+// for (String method : LightweightMetricAspect.metrics.keySet()) {
+// LightweightMetrics sc = LightweightMetricAspect.metrics.get(method);
+//
+// logger.info("Testing {} with frequency {} and expensiveness {}", sc
+// , frequencies.getMean() + frequencies.getStandardDeviation()
+// , expensiveness.getMean() + expensiveness.getStandardDeviation());
+// if (sc.getFrequency() > (frequencies.getMean() + frequencies.getStandardDeviation())
+// && sc.getExpensiveness() > (expensiveness.getMean() + expensiveness.getStandardDeviation()))
+// allowedFineGrained.add(sc.getLongName());
+// }
+
+ //Example: more frequent U more expensive
+ for(String method : LightweightMetricAspect.metrics.keySet()) {
+ LightweightMetrics sc = LightweightMetricAspect.metrics.get(method);
+ if(sc.getFrequency() > (frequencies.getMean() + frequencies.getStandardDeviation())
+ || sc.getExpensiveness() > (expensiveness.getMean() + expensiveness.getStandardDeviation()))
+ allowedFineGrained.add(sc.getLongName());
+ }
+
+ logger.info("Selected methods for fine-grained: {}", allowedFineGrained);
+
+//
+// //Example: less frequent
+// for(String method : LightweightMetricAspect.metrics.keySet()) {
+// LightweightMetrics sc = LightweightMetricAspect.metrics.get(method);
+// if(sc.getFrequency() < (frequencies.getMean() - frequencies.getStandardDeviation()))
+// allowedFineGrained.add(sc.getLongName());
+// }
+//
+// //Example: frequent
+// for(String method : LightweightMetricAspect.metrics.keySet()) {
+// LightweightMetrics sc = LightweightMetricAspect.metrics.get(method);
+// if(sc.getFrequency() >= (frequencies.getMean() - frequencies.getStandardDeviation())
+// && sc.getFrequency() <= (frequencies.getMean() + frequencies.getStandardDeviation()))
+// allowedFineGrained.add(sc.getLongName());
+// }
+
+ }
+
+ @Override
+ public void run() {
+ logger.info("Lightweight calculating metrics and updating coarse-monitoring into {} methods...", allowedFineGrained);
+ analyze();
+ }
+}
diff --git a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightMetricAspect.java b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightMetricAspect.java
index ad6e807..5d7913f 100644
--- a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightMetricAspect.java
+++ b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightMetricAspect.java
@@ -1,14 +1,32 @@
package br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics;
+import br.ufrgs.inf.prosoft.adaptivecaching.analysis.Analyzer;
+import br.ufrgs.inf.prosoft.adaptivecaching.cachemanager.util.threads.NamedThreads;
+import br.ufrgs.inf.prosoft.adaptivecaching.configuration.annotation.AdaptiveCaching;
+import br.ufrgs.inf.prosoft.adaptivecaching.configuration.annotation.ComponentScan;
+import br.ufrgs.inf.prosoft.adaptivecaching.exceptions.ConfigurationException;
+import br.ufrgs.inf.prosoft.adaptivecaching.monitoring.application.usersession.UserGetter;
+import br.ufrgs.inf.prosoft.adaptivecaching.monitoring.application.usersession.UserGetterFactory;
+import br.ufrgs.inf.prosoft.adaptivecaching.sampling.annotations.Criteria;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
-
-import java.util.HashMap;
-import java.util.Map;
+import org.reflections.Reflections;
+import org.reflections.scanners.ResourcesScanner;
+import org.reflections.scanners.SubTypesScanner;
+import org.reflections.scanners.TypeAnnotationsScanner;
+import org.reflections.util.ClasspathHelper;
+import org.reflections.util.ConfigurationBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import static java.lang.System.currentTimeMillis;
@@ -16,30 +34,74 @@ import static java.lang.System.currentTimeMillis;
public class LightweightMetricAspect {
@Pointcut(
- //any execution except the own framework
- "execution(!void *(..)) && !within(br.ufrgs.inf.prosoft.adaptivecaching..*) " +
- //avoid calls from repository while serializing objects, it is necessary if a hash could not be used
- "&& !cflow(call(* br.ufrgs.inf.prosoft.adaptivecaching.monitoring.storage..*(..)))"
+ //any execution except the own framework
+ "execution(!void *(..)) && !within(br.ufrgs.inf.prosoft.adaptivecaching..*) " +
+ //avoid calls from repository while serializing objects, it is necessary if a hash could not be used
+ "&& !cflow(call(* br.ufrgs.inf.prosoft.adaptivecaching.monitoring.storage..*(..)))"
)
public void anyCall() {
}
+ Logger logger = LoggerFactory.getLogger(LightweightMetricAspect.class);
+
+ private final ScheduledExecutorService analyzerExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreads(
+ "lightweight-analyzer",
+ "computing lightweight metrics and setting allowedmethods"
+ ));
+
public static Map<String, LightweightMetrics> metrics;
+ private UserGetter userGetter;
+
+ //traceable configuration
+ private String[] allowed;
+ private String[] notAllowed;
+
+ public static String criteriaDSL = "";
public LightweightMetricAspect() {
metrics = new HashMap<>();
+ userGetter = UserGetterFactory.getInstance();
+
+ Class<?> configClass = getAvailableConfigurationClass();
+
+ //getting criteria DSL
+ Criteria criteria = configClass.getAnnotation(Criteria.class);
+ criteriaDSL = criteria.value();
+
+ //getting allowed packages from @ComponentScan
+ ComponentScan componentScanConfig = configClass.getAnnotation(ComponentScan.class);
+ if (componentScanConfig == null) {
+ //if not specified, it assumes the same package where @AdaptiveCaching were declared
+ allowed = new String[]{configClass.getPackage().getName()};
+ //logger.error("ComponenScan for AdaptiveCaching not found, adaptive caching disabled.");
+ //enabled = false;
+ //return;
+ }
+ allowed = componentScanConfig.allowed();
+ notAllowed = componentScanConfig.denied();
+ logger.info("Lightweight monitoring will trace methods into {} packages...", allowed);
+
+ analyzerExecutor.scheduleWithFixedDelay(
+ new LightweightAnalyzer(),
+ 60000, 150000, TimeUnit.MILLISECONDS);
+
}
@Around("anyCall()")
public Object aroundMethods(ProceedingJoinPoint joinPoint) throws Throwable {
+ if (!isAllowed(joinPoint))
+ return joinPoint.proceed();
+
String signature = joinPoint.getSignature().toString();
LightweightMetrics metric = metrics.get(signature);
- if(metric != null)
+ if (metric != null)
metric.incOccurrence();
else {
- metric = new LightweightMetrics();
+ String name = joinPoint.getSignature().toString().split(" ")[1];
+ name = name.substring(0, name.indexOf("("));
+ metric = new LightweightMetrics(name, joinPoint.getSignature().toLongString());
metric.incOccurrence();
metrics.put(signature, metric);
}
@@ -53,29 +115,60 @@ public class LightweightMetricAspect {
Object result = joinPoint.proceed();
long endTime = currentTimeMillis();
- metric.addTime(startTime,endTime - startTime);
+ metric.addTime(startTime, endTime - startTime);
long endMemory = runtime.totalMemory() - runtime.freeMemory();
metric.addMemoryConsumption(endMemory - startMemory);
long endThread = java.lang.Thread.activeCount();
metric.addThreadNumber(endThread - startThread);
-
-
+ metric.addReturnSize(result);
+ metric.addUser(userGetter.getCurrentUser());
return result;
}
@AfterThrowing(pointcut = "anyCall()", throwing = "e")
public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
+ String signature = joinPoint.getSignature().toString();
+ LightweightMetrics metric = metrics.get(signature);
+ metric.incThrown();
+ }
+ private boolean isAllowed(ProceedingJoinPoint joinPoint) throws Throwable {
String signature = joinPoint.getSignature().toString();
+ if (signature.contains("br.ufrgs.inf.prosoft.adaptivecaching")) {
+ return false;
+ }
- LightweightMetrics metric = metrics.get(signature);
- if(metric != null)
- metric.incThrown();
- else {
- metric = new LightweightMetrics();
- metric.incThrown();
- metrics.put(signature, metric);
+ for (String p : notAllowed) {
+ //toString to avoid get the return class as a false positive
+ if (signature.contains(p)) {
+ return false;
+ }
}
+
+ //trace only allowed packages
+ for (String p : allowed) {
+ if (joinPoint.getSignature().toLongString().contains(p))
+ return true;
+ }
+
+ return false;
+ }
+
+ private Class<?> getAvailableConfigurationClass() {
+ //TODO Decouple??
+ Reflections reflections = new Reflections(
+ new ConfigurationBuilder()
+ .setUrls(ClasspathHelper.forClassLoader())
+ .setScanners(new SubTypesScanner(false), new ResourcesScanner(), new TypeAnnotationsScanner()));
+
+ //loading @AdaptiveCaching
+ Set<Class<?>> configurations =
+ reflections.getTypesAnnotatedWith(AdaptiveCaching.class);
+ if (configurations.isEmpty())
+ throw new ConfigurationException("@AdaptiveCaching not found, adaptive caching disabled.");
+ if (configurations.size() > 1)
+ throw new ConfigurationException("@AdaptiveCaching has too many definitions, adaptive caching disabled.");
+ return configurations.iterator().next();
}
}
diff --git a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightMetrics.java b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightMetrics.java
index 79e5714..8538dcf 100644
--- a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightMetrics.java
+++ b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/LightweightMetrics.java
@@ -1,50 +1,80 @@
package br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics;
-import org.apache.commons.math3.stat.StatUtils;
-import org.apache.commons.math3.util.FastMath;
+import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
+import org.ehcache.sizeof.SizeOf;
+import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
public class LightweightMetrics {
private long occurrences;
- private List<Long> times;
- private List<Long> memories;
- private List<Long> threadNumber;
- private long throwns;
+ private SummaryStatistics timeStatistics;
+ private SummaryStatistics memoryStatistics;
+ private SummaryStatistics threadStatistics;
+ private SummaryStatistics intervalStatistics;
+ private long thrownCounter;
private List<Long> startTimes;
+ private SummaryStatistics returnSizeStatistics;
+ private static SizeOf sizeOf = SizeOf.newInstance();
+ private Set<String> users;
+ private String name;
+ private String longName;
+ private StaticMetrics staticMetrics;
- //not able to get CPU usage
-
- public LightweightMetrics(){
+ public LightweightMetrics(String name, String longName) throws IOException {
+ this.name = name;
+ this.longName = longName;
startTimes = new ArrayList<>();
- times = new ArrayList<>();
- memories = new ArrayList<>();
- threadNumber = new ArrayList<>();
+ timeStatistics = new SummaryStatistics();
+ memoryStatistics = new SummaryStatistics();
+ threadStatistics = new SummaryStatistics();
+ returnSizeStatistics = new SummaryStatistics();
+ intervalStatistics = new SummaryStatistics();
+ intervalStatistics.addValue(0);
+ users = new HashSet<>();
+ staticMetrics = new StaticMetrics();
}
public void addTime(long startTime, long time){
startTimes.add(startTime);
- times.add(time);
+ timeStatistics.addValue(time);
+ if(startTimes.size() == 1)
+ intervalStatistics.addValue(0);
+ else
+ intervalStatistics.addValue(startTime - startTimes.get(startTimes.size() - 2));
}
public void addThreadNumber(long threads){
- threadNumber.add(threads);
+ threadStatistics.addValue(threads);
}
public void addMemoryConsumption(long memory){
- memories.add(memory);
+ memoryStatistics.addValue(memory);
+ }
+
+ public void addReturnSize(Object returnObject){
+ if(returnObject != null)
+ returnSizeStatistics.addValue(sizeOf.sizeOf(returnObject));
+ else
+ returnSizeStatistics.addValue(0);
}
public void incThrown() {
- throwns++;
+ thrownCounter++;
}
public void incOccurrence() {
occurrences++;
}
+ public void addUser(String currentUser) {
+ users.add(currentUser);
+ }
+
public List<Long> interIntervals(){
List<Long> intervalTimes = new ArrayList<>();
long lastTime = startTimes.get(0);
@@ -55,14 +85,88 @@ public class LightweightMetrics {
return intervalTimes;
}
- public long getOccurrences() {
+ /**
+ *
+ * @return number of occurrences
+ */
+ public long getFrequency() {
return occurrences;
}
+ /**
+ *
+ * @return number of different users
+ */
+ public long getUserBehavior(){
+ return users.size();
+ }
+
+ /**
+ *
+ * @return throughput
+ */
+ public double getLatency(){
+ return (startTimes.get(startTimes.size()-1) - startTimes.get(0)) / startTimes.size();
+ }
+
+ /**
+ *
+ * @return inter interval times
+ */
+ public double getConcurrency(){
+ return intervalStatistics.getMean();
+ }
+
+ /**
+ *
+ * @return processing times
+ */
+ public double getExpensiveness(){
+ return timeStatistics.getMean();
+ }
+
+ /**
+ *
+ * @return class size
+ */
+ public double getChangeability(){
+ return returnSizeStatistics.getMean();
+ }
+
+ /**
+ *
+ * @return number of exceptions raised
+ */
+ public long getDynamicErrorprone(){
+ return thrownCounter;
+ }
+
+ public long getStaticErrorprone(){
+ return staticMetrics.getMetrics(name).maxNesting;
+ }
+
+ public long getMaintainability(){
+ return staticMetrics.getMetrics(name).cyclomatic;
+ }
+
+ public long getGlobalImpact(){
+ return staticMetrics.getMetrics(name).countOutput;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getLongName() {
+ return longName;
+ }
+
@Override
public String toString() {
- return "{" +
- "occurrences=" + occurrences +
+ return "LightweightMetrics{" +
+ "name='" + name + '\'' +
+ ", frequency=" + getFrequency() +
+ ", expensiveness=" + getExpensiveness() +
'}';
}
}
diff --git a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/StaticMetrics.java b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/StaticMetrics.java
new file mode 100644
index 0000000..0cac98d
--- /dev/null
+++ b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/metrics/StaticMetrics.java
@@ -0,0 +1,58 @@
+package br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics;
+
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class StaticMetrics {
+
+ private Map<String, StaticMetric> metrics;
+
+ public StaticMetrics() throws IOException {
+ loadMetrics();
+ }
+
+ public StaticMetric getMetrics(String method){
+ return metrics.get(method);
+ }
+
+ public void loadMetrics() throws IOException {
+ BufferedReader br = new BufferedReader(new FileReader("/home/jhonnymertz/workspace/adaptive-caching-framework/understand/petclinic.csv"));
+ String line = null;
+ metrics = new HashMap<>();
+
+ while ((line = br.readLine()) != null) {
+ if (line.contains("Kind")) continue;
+ String str[] = line.split(",");
+ metrics.put(str[1], new StaticMetric(Long.valueOf(str[2]), Long.valueOf(str[3]), Long.valueOf(str[4])));
+ }
+ }
+
+ public Map<String, StaticMetric> getAllMetrics() {
+ return metrics;
+ }
+
+ class StaticMetric {
+ public long countOutput;
+ public long cyclomatic;
+ public long maxNesting;
+
+ public StaticMetric(long countOutput, long cyclomatic, long maxNesting) {
+ this.countOutput = countOutput;
+ this.cyclomatic = cyclomatic;
+ this.maxNesting = maxNesting;
+ }
+
+ @Override
+ public String toString() {
+ return "StaticMetric{" +
+ "countOutput=" + countOutput +
+ ", cyclomatic=" + cyclomatic +
+ ", maxNesting=" + maxNesting +
+ '}';
+ }
+ }
+}
diff --git a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/statistics/StatisticalTest.java b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/statistics/StatisticalTest.java
index d3596bd..7ebe3f7 100644
--- a/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/statistics/StatisticalTest.java
+++ b/framework/autonomicmanager/src/main/java/br/ufrgs/inf/prosoft/adaptivecaching/sampling/statistics/StatisticalTest.java
@@ -6,16 +6,12 @@ import org.apache.commons.math3.stat.inference.TestUtils;
public class StatisticalTest {
- public static void isNormalDistribution(){
- //commons math
-// final NormalDistribution unitNormal = new NormalDistribution(0d, 1d);
-// TestUtils.kolmogorovSmirnovTest(unitNormal, sample, false);
+ public static boolean isNormalDistribution(double[] sample, double significanceLevel){
+ final NormalDistribution unitNormal = new NormalDistribution(0d, 1d);
+ System.out.println("p-value: " + TestUtils.kolmogorovSmirnovTest(unitNormal, sample, false));
-
- //https://github.com/umontreal-simul/ssj
-
- //http://jdistlib.sourceforge.net/
-// NormalityTest.xxx_statistic(double[] x);
-// NormalityTest.xxx_p_value(double stat, int df);
+ //alpha significance level (equiv. 100 * (1-alpha)% confidence) where 0 < alpha < 1 use
+ //Significance level of 95%: 100 * (1-0.05)
+ return TestUtils.kolmogorovSmirnovTest(unitNormal, sample, significanceLevel);
}
}
diff --git a/framework/autonomicmanager/src/test/java/br/ufrgs/inf/prosoft/sampling/StaticMetricsTest.java b/framework/autonomicmanager/src/test/java/br/ufrgs/inf/prosoft/sampling/StaticMetricsTest.java
new file mode 100644
index 0000000..8968e61
--- /dev/null
+++ b/framework/autonomicmanager/src/test/java/br/ufrgs/inf/prosoft/sampling/StaticMetricsTest.java
@@ -0,0 +1,15 @@
+package br.ufrgs.inf.prosoft.sampling;
+
+import br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics.StaticMetrics;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class StaticMetricsTest {
+
+ @Test
+ public void loadMetrics() throws IOException {
+ StaticMetrics staticMetrics = new StaticMetrics();
+ System.out.println(staticMetrics.getAllMetrics());
+ }
+}
diff --git a/framework/autonomicmanager/src/test/java/br/ufrgs/inf/prosoft/sampling/Statistics.java b/framework/autonomicmanager/src/test/java/br/ufrgs/inf/prosoft/sampling/Statistics.java
new file mode 100644
index 0000000..7a278db
--- /dev/null
+++ b/framework/autonomicmanager/src/test/java/br/ufrgs/inf/prosoft/sampling/Statistics.java
@@ -0,0 +1,81 @@
+package br.ufrgs.inf.prosoft.sampling;
+
+import br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics.LightweightMetricAspect;
+import br.ufrgs.inf.prosoft.adaptivecaching.sampling.metrics.LightweightMetrics;
+import br.ufrgs.inf.prosoft.adaptivecaching.sampling.statistics.StatisticalTest;
+import org.apache.commons.math3.distribution.NormalDistribution;
+import org.apache.commons.math3.random.EmpiricalDistribution;
+import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
+import org.junit.Assert;
+import org.junit.Test;
+import umontreal.ssj.gof.GofStat;
+import umontreal.ssj.probdist.NormalDist;
+
+import java.util.Arrays;
+
+public class Statistics {
+
+ public void test(double[] sample){
+ DescriptiveStatistics frequencies = new DescriptiveStatistics();
+ for(double d : sample){
+ frequencies.addValue(d);
+ }
+ System.out.println("KS pvalue should be higher than significance level (0.05): "
+ + ((StatisticalTest.isNormalDistribution(frequencies.getValues(), 0.5)) ? " yes" : " no"));
+
+ Arrays.sort(sample);
+ double[] adresult = GofStat.andersonDarling(sample, new NormalDist());
+ System.out.println("Dstat: " + adresult[0] + " pvalue:" + adresult[1]);
+ }
+
+ @Test
+ public void normalization(){
+
+ double[] sample = {4.50e+1, 5.20e+1, 4.30e+1,4.90e+1,4.80e+1,5.40e+1,5.30e+1,4.90e+1,4.90e+1};
+ test(sample);
+// double d_stat = TestUtils.kolmogorovSmirnovStatistic(unitNormal, sample);
+
+ test(new double[]{2, 3, 3, 4, 3, 3, 2});
+ test(new double[]{93.0, 103.0, 95.0, 101.0, 91.0, 105.0, 96.0, 94.0, 101.0});
+ test(new double[]{26, 33, 65, 28, 34, 25, 55, 44, 50, 36, 26, 37, 43, 62, 35, 38, 45, 32, 28, 34});
+ test(new double[]{20, 15, 26, 32, 18, 28, 35, 14, 26, 22, 17});
+ test(new double[]{565, 116, 69, 78, 319, 501, 633, 655, 848, 1226, 1633, 2459, 3375, 4669, 6152, 7436, 9526, 12619, 12455, 7113, 2104, 241});
+ test(new double[]{9.0964868007346, 9.05841203941304, 10.4561973049786, 11.4290519020928, 9.80406201402498, 8.00495612940127, 10.9560511244096, 10.1628617100704, 9.5404880778431, 8.31409730387256, 10.5850756498228, 8.94573786127721, 9.67884319773862, 10.2674043676357, 8.88672394683865, 12.3582450296069, 11.3323127708954, 8.98248290920661, 10.0195219450004, 10.2978738217737, 8.12677492317708, 8.89950454463237, 9.77696513465945, 10.514898975753, 10.672289112785, 10.694498534934, 10.1821924686095, 11.142573152688, 9.77887037458247, 11.0049010075665, 10.2154096657666, 9.85591747299326, 8.42526783048421, 9.81110530928476, 10.8197900519108, 10.3297258106185, 10.0227636883243, 11.2987975587751, 8.44486064977259, 11.5225576269198, 8.12224293685105, 10.0007857247433, 11.5138891839899, 9.3831006575966, 8.12476347171477, 9.09856941554296, 8.62142101694361, 9.46470997205525, 9.41790826247466, 8.48703712461685, 10.2715646747326, 9.33049825280273, 10.6699012172013, 9.18072916828602, 8.41649117636405, 9.33567958667778, 10.049876040196, 11.3127990745231, 11.6586896309607, 8.89584835227498, 9.70752934278868, 8.86246838225148, 10.2161331491117, 9.85382278972802, 9.05752306126498, 11.3505257827677, 8.44762586593948, 9.15864805742191, 9.57567977055168, 11.7688636824855, 10.2024057615904, 10.3104037114343, 10.1580229817262, 10.0680455332437, 9.91423812485741, 9.94504630463698, 8.52395458741078, 10.2521461941422, 10.1036308255006, 9.18956474594286, 9.96954494398682, 9.78104199181701, 9.92382325277581, 8.63597929467619, 9.21347593192941, 9.89855218854907, 11.0121033672495, 9.63264753881509, 10.6248219653335, 10.486189745896, 10.5244954307719, 8.53373914749441, 9.3983432649672, 11.0903843560089, 9.44459585712476, 10.0859955061661, 11.3387705764577, 9.84586163010232, 11.4741429769762, 10.441848372811, 9.55045713422817, 10.6267816577505, 10.4443547888383, 9.89379735185878, 9.72354469139489, 9.12066768498717, 10.0661011719204, 10.3323960556678, 11.505082984854, 10.7859172636304, 11.8287650643979, 10.4116817822928, 10.1463678500856, 9.25763259285018, 8.95707586672983, 10.2875032181518, 9.73858400501329, 8.70348547219759, 9.14762353313967, 9.82731108963226, 10.849859681053, 10.5423597494633, 8.58089709606474, 8.47543607758568, 9.15931239135863, 9.27560590704311, 10.5368346988892, 9.83172309690772, 9.16056782666665, 9.2012213506938, 9.66210982564607, 10.5190510051426, 8.62151894187291, 9.90524992792067, 10.138710665855, 9.30829258153867, 10.8290286694516, 12.1178308609245, 9.50553095064575, 9.95398394895215, 12.0245206821336, 10.2477642478284, 8.55456942605116, 11.6070473804305, 10.1562361056329, 9.43630469486672, 10.3170511798909, 9.01652208335814, 9.86807032119238, 10.8489404774946, 10.7826270556231, 10.0870496269544, 10.9833771671752, 10.117870221528, 10.5996195058974, 11.0329621602774, 10.4132314334195, 9.74158685858501, 9.48294737415442, 9.86849961215289, 9.91013610376275, 7.83468897764531, 10.514842063025, 11.4804302009497, 10.1196554587607, 10.39118899319, 9.62353860043821, 8.97417942332151, 9.35318610423095, 10.3556147738602, 11.9155451973464, 8.27736636882948, 9.32257441690336, 10.252826149316, 9.7535116214245, 10.9162334195511, 10.1678750592301, 10.9559458131311, 8.60102009638715, 9.2628210057096, 9.78873072091305, 8.35114511028973, 10.1637620813489, 9.46509546070039, 8.29088640463265, 11.1023522365736, 8.23070146296037, 9.21646018542163, 8.78784331889502, 10.2988093157657, 10.537263338189, 10.8732424762337, 10.0350589477381, 8.64559077573426, 9.82216826151432, 12.9407607539763, 9.58702405409422, 8.68540299123893, 8.90868676037665, 9.83588804978778, 9.45456213634599, 9.88659569326315, 9.46423529809919, 8.51323166422944, 9.06114471768126, 7.0763024483504, 11.3048132198129, 10.9310615911962, 10.243499074504, 12.2494232010316, 9.92165717330645, 11.1055496127494, 10.3824281515872, 10.9363315824212, 9.47366362946216, 10.5074206502971, 9.92574082866448, 9.98656454297378, 10.3434126760638, 9.16080972535168, 10.6397501919665, 8.88350130241863, 10.2657096522122, 9.29382344383002, 10.2707284719202, 10.6950720070684, 10.5671180659654, 8.58795244344749, 9.50269445287456, 10.5319945577608, 10.8884770667036, 10.2324575999004, 9.32891854565115, 8.9740321510626, 10.4126653257714, 9.98364553876901, 10.0039606824373, 11.373614936858, 8.33792326220959, 8.42278194538867, 8.92005049489281, 9.56511841862538, 10.6829314510294, 10.6412977717579, 11.1075024003369, 10.5483699986234, 10.3218235881083, 9.91439811222411, 10.0027837642839, 9.50565960381905});
+
+
+ //https://github.com/umontreal-simul/ssj
+
+ //http://jdistlib.sourceforge.net/
+// NormalityTest.xxx_statistic(double[] x);
+// NormalityTest.xxx_p_value(double stat, int df);
+ }
+
+ @Test
+ public void testCalculatePercentile() {
+ //given
+ double[] values = new double[]{1,2,3,4,5};
+
+ EmpiricalDistribution distribution = new EmpiricalDistribution(values.length);
+ distribution.load(values);
+
+ //when
+ double percentile = distribution.cumulativeProbability(4);
+
+ //then
+ Assert.assertEquals(percentile, 0.8, 0.1);
+ }
+
+ @Test
+ public void testQuantiles(){
+ DescriptiveStatistics frequencies = new DescriptiveStatistics();
+ double[] values = new double[]{7.1, 7.4, 7.5, 7.7, 7.8, 7.9};
+ for(double d : values)
+ frequencies.addValue(d);
+
+ //then
+ Assert.assertEquals(frequencies.getPercentile(25), 7.325, 0.1);
+ Assert.assertEquals(frequencies.getPercentile(50), 7.6, 0.1);
+ Assert.assertEquals(frequencies.getPercentile(75), 7.825, 0.1);
+ }
+
+}