adaptive-monitoring-framework

first version of the approach

5/8/2021 3:24:26 PM

Details

diff --git a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/FrequencyDataSet.java b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/FrequencyDataSet.java
index 0066458..74c03b6 100644
--- a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/FrequencyDataSet.java
+++ b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/FrequencyDataSet.java
@@ -24,6 +24,10 @@ public class FrequencyDataSet {
         return statistics.getMean();
     }
 
+    public double getStdExecutionTime(){
+        return statistics.getStandardDeviation();
+    }
+
     public long getTotalItems(){
         return n;
     }
@@ -32,7 +36,11 @@ public class FrequencyDataSet {
         Integer occurrences = granularityPopulation.get(granularity);
         if (occurrences == null)
             return 0;
-        return new BigDecimal(occurrences).divide(new BigDecimal(getTotalItems()), MathContext.DECIMAL128).doubleValue();
+        try {
+            return new BigDecimal(occurrences).divide(new BigDecimal(getTotalItems()), MathContext.DECIMAL128).doubleValue();
+        } catch (Exception e) {
+            return 0;
+        }
     }
 
     public Set<Granularity> getGranularities(){
@@ -61,6 +69,7 @@ public class FrequencyDataSet {
 
     public void clear() {
         granularityPopulation.clear();
+        statistics.clear();
         n = 0;
     }
 }
diff --git a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/MonitoringCycle.java b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/MonitoringCycle.java
index a7eb693..f0c6769 100644
--- a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/MonitoringCycle.java
+++ b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/MonitoringCycle.java
@@ -2,27 +2,51 @@ package br.ufrgs.inf.prosoft.tigris.sampling;
 
 public class MonitoringCycle {
     private double averageProcTimesSample;
+    private double stdProcTimesSample;
     private double averageProcTimesPopulation;
+    private double stdProcTimesPopulation;
     private long sampleSize;
     private long populationSize;
 
-    public MonitoringCycle(double averageProcTimesSample, double averageProcTimesPopulation, long sampleSize, long populationSize) {
-        this.averageProcTimesSample = averageProcTimesSample;
-        this.averageProcTimesPopulation = averageProcTimesPopulation;
-        this.sampleSize = sampleSize;
-        this.populationSize = populationSize;
+    public MonitoringCycle(FrequencyDataSet sample, FrequencyDataSet population) {
+        this.averageProcTimesSample = sample.getMeanExecutionTime();
+        this.stdProcTimesSample = sample.getStdExecutionTime();
+        this.sampleSize = sample.getTotalItems();
+
+        this.averageProcTimesPopulation = population.getMeanExecutionTime();
+        this.stdProcTimesPopulation = population.getStdExecutionTime();
+        this.populationSize = population.getTotalItems();
+    }
+
+    public MonitoringCycle() {
+        this.averageProcTimesSample = 0;
+        this.stdProcTimesSample = 0;
+        this.sampleSize = 0;
+        this.averageProcTimesPopulation = 0;
+        this.stdProcTimesPopulation = 0;
+        this.populationSize = 0;
     }
 
     @Override
     public String toString() {
         return "MonitoringCycle{" +
                 "averageProcTimesSample=" + averageProcTimesSample +
+                ", stdProcTimesSample=" + stdProcTimesSample +
                 ", averageProcTimesPopulation=" + averageProcTimesPopulation +
+                ", stdProcTimesPopulation=" + stdProcTimesPopulation +
                 ", sampleSize=" + sampleSize +
                 ", populationSize=" + populationSize +
                 '}';
     }
 
+    public double getStdProcTimesSample() {
+        return stdProcTimesSample;
+    }
+
+    public double getStdProcTimesPopulation() {
+        return stdProcTimesPopulation;
+    }
+
     public double getAverageProcTimesSample() {
         return averageProcTimesSample;
     }
diff --git a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/Sampling.java b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/Sampling.java
index d8f4059..896b6f2 100644
--- a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/Sampling.java
+++ b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/Sampling.java
@@ -165,6 +165,29 @@ public class Sampling {
         }
     }
 
+    private long maxOps = 0;
+    private long minOps = Integer.MAX_VALUE;
+    public double adaptSamplingRateInverselyProportional(long currentOps) {
+        synchronized (samplingRateLock) {
+
+            if (minOps > currentOps)
+                minOps = currentOps;
+
+            if (currentOps > maxOps)
+                maxOps = currentOps;
+
+            samplingRate = 1 - ((double) (currentOps - minOps) / (maxOps - minOps));
+
+            if (samplingRate == 0)
+                samplingRate = 0.01;
+
+            //update the binomial with the new sampling rate distribution
+            resetSamplingDistribution();
+            logger.info("New sampling rate: {}", samplingRate);
+            return samplingRate;
+        }
+    }
+
     public void addPerformanceBaselineItem(Granularity granularity, long executionTime) {
         if(this.performanceBaselineDataSet.getTotalItems() < minimumSampleSize) {
             this.performanceBaselineDataSet.addItem(granularity, executionTime);
@@ -256,7 +279,7 @@ public class Sampling {
     private Object decayingPrecisionLock = new Object();
     public void startMonitoringCycle() {
         synchronized (decayingPrecisionLock) {
-            this.decayingPrecision = new ExponentialDecayFunction(1, 0.001, cycleLengthInMilliseconds);
+            this.decayingPrecision = new ExponentialDecayFunction(1, 0.1, cycleLengthInMilliseconds);
         }
         this.sample.clear();
         this.population.clear();
@@ -266,11 +289,7 @@ public class Sampling {
     }
 
     public MonitoringCycle endMonitoringCycle() {
-        MonitoringCycle monitoringCycle = new MonitoringCycle(
-                getSample().getMeanExecutionTime(),
-                getPopulation().getMeanExecutionTime(),
-                getSample().getTotalItems(),
-                getPopulation().getTotalItems());
+        MonitoringCycle monitoringCycle = new MonitoringCycle(getSample(), getPopulation());
         logger.info("Adaptive Sampling Monitoring Cycle Finished: {}", monitoringCycle);
         startMonitoringCycle();
         return monitoringCycle;
@@ -284,7 +303,8 @@ public class Sampling {
                 performanceBaselineEnabled = false;
                 minimumSampleSize = null;
 //                lastFourPerformanceBaselineDataSets.add(this.performanceBaselineDataSet);
-                adaptSamplingRate(); //adapt the sampling rate
+
+                adaptSamplingRate(); //adapt the sampling rate based on heuristic
                 this.performanceBaselineDataSet.clear();
             }
             return;
diff --git a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/SamplingAspect.java b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/SamplingAspect.java
index 309d9d4..de23118 100644
--- a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/SamplingAspect.java
+++ b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/SamplingAspect.java
@@ -26,9 +26,31 @@ public class SamplingAspect implements Runnable {
     @Pointcut(
             //any execution except the own framework
             "(" +
-                    "(execution(* org.dacapo.h2.TPCCSubmitter.runTransaction(..)) || " + //h2
-                    "execution(* org.dacapo.lusearch.QueryProcessor.doPagingSearch(..)) || " + //lusearch
-                    "execution(* org.dacapo.xalan.XalanWorker.transform(..))) " + //xalan
+                    "(" +
+                        "execution(* org.dacapo.h2.TPCCSubmitter.runTransaction(..)) || " + //h2
+                        "execution(* org.dacapo.lusearch.QueryProcessor.doPagingSearch(..)) || " + //lusearch
+                        "execution(* org.dacapo.xalan.XalanWorker.transform(..)) || " + //xalan
+
+                        //tradebeans:
+                        "(" +
+                        "execution(* org.apache.geronimo.daytrader.javaee6.dacapo.DaCapoTrader.doHome(..)) || " +
+                        "execution(* org.apache.geronimo.daytrader.javaee6.dacapo.DaCapoTrader.doPortfolio(..)) || " +
+                        "execution(* org.apache.geronimo.daytrader.javaee6.dacapo.DaCapoTrader.doQuote(..)) || " +
+                        "execution(* org.apache.geronimo.daytrader.javaee6.dacapo.DaCapoTrader.doBuy(..)) || " +
+                        "execution(* org.apache.geronimo.daytrader.javaee6.dacapo.DaCapoTrader.doUpdate(..)) || " +
+                        "execution(* org.apache.geronimo.daytrader.javaee6.dacapo.DaCapoTrader.doRegister(..)) || " +
+                        "execution(* org.apache.geronimo.daytrader.javaee6.dacapo.DaCapoTrader.doSell(..))" +
+                        ") || " +
+                        //cassandra:
+                        "(" +
+                            "execution(* site.ycsb.workloads.CoreWorkload.doTransactionRead(..)) || " +
+                            "execution(* site.ycsb.workloads.CoreWorkload.doTransactionUpdate(..)) || " +
+                            "execution(* site.ycsb.workloads.CoreWorkload.doTransactionInsert(..)) || " +
+                            "execution(* site.ycsb.workloads.CoreWorkload.doTransactionScan(..)) || " +
+                            "execution(* site.ycsb.workloads.CoreWorkload.doTransactionReadModifyWrite(..))" +
+                        ")" +
+                    ") " +
+
 //            "(execution(* *(..)) && !within(br.ufrgs.inf.prosoft..*) " +
                     //avoid calls from repository while serializing objects, it is necessary if a hash could not be used
                     //"&& !cflow(call(* br.ufrgs.inf.prosoft.tigris.monitoring.storage..*(..))) " +
@@ -43,9 +65,14 @@ public class SamplingAspect implements Runnable {
     private final TigrisConfiguration tigrisConfiguration;
     private static Sampling sampling;
 
-    public SamplingAspect() {
+    public SamplingAspect() throws ClassNotFoundException {
         Class<?> configClass = ConfigurationUtils.getAvailableConfigurationClass(TigrisConfiguration.class);
         if (configClass == null) {
+            //workaround for cassandra
+            configClass = Class.forName("site.ycsb.ApplicationInitializer");
+        }
+
+        if (configClass == null) {
             logger.info("Tigris tracing disabled, there is no annotations.");
             throw new ConfigurationException("Tigris tracing disabled, there is no annotations.");
         }
@@ -74,33 +101,52 @@ public class SamplingAspect implements Runnable {
 
     @Around("anyCall()")
     public Object aroundMethods(ProceedingJoinPoint joinPoint) throws Throwable {
+//        String signature = joinPoint.getSignature().toString();
+//        System.err.println(signature);
+
         long startTime = nanoTime();
         Object result = joinPoint.proceed();
         long endTime = nanoTime();
+        long totalTime = endTime - startTime;
 
         if (samplingEnabled) {
-            String signature = joinPoint.getSignature().toString() +
-                    joinPoint.getArgs()[0].toString(); //TODO this is to distinguish traces, need to change for other than h2 or lusearch
+            String signature = joinPoint.getSignature().toString() + joinPoint.getArgs()[0].toString(); //TODO this is to distinguish traces in H2 or lusearch / also run with Xalan / cassandra / tradebeans?
             Granularity granularity = new Granularity(GranularityType.METHOD, signature);
             if (sampling.isPerformanceBaselineEnabled()) {
-                sampling.addPerformanceBaselineItem(granularity, endTime - startTime);
+                sampling.addPerformanceBaselineItem(granularity, totalTime);
                 return result;
             }
 
-            boolean decision = sampling.samplingDecision(granularity, endTime - startTime);
+            boolean decision = sampling.samplingDecision(granularity, totalTime);
 
             if (decision)
-                sampling.addSampledItem(granularity, nanoTime() - startTime);
+//                sampling.addSampledItem(granularity, nanoTime() - startTime);
+                sampling.addSampledItem(granularity, totalTime);
         }
 
         return result;
     }
 
     static double currentSamplingRate;
-    static MonitoringCycle cycle = new MonitoringCycle(0,0,0,0);
+    static MonitoringCycle cycle = new MonitoringCycle();
 
+    //used for the baseline with inversely proportional sampling
+    public static long currentOps = 0;
+    public static long currentUsers = 0;
+    public static boolean adaptSamplingRateInverselyProportionalOps = false;
+    public static boolean adaptSamplingRateInverselyProportionalUsers = false;
     @Override
     public void run() {
+        if (adaptSamplingRateInverselyProportionalOps) {
+            currentSamplingRate = sampling.adaptSamplingRateInverselyProportional(currentOps);
+            return;
+        }
+
+        if (adaptSamplingRateInverselyProportionalUsers) {
+            currentSamplingRate = sampling.adaptSamplingRateInverselyProportional(currentUsers);
+            return;
+        }
+
         if (SamplingAspect.enabled && sampling.isAdaptiveSamplingRate()) {
             sampling.managePerformanceBaseline();
             currentSamplingRate = sampling.getSamplingRate();
diff --git a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/utils/ConfigurationUtils.java b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/utils/ConfigurationUtils.java
index 0834b9f..bc46ab9 100644
--- a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/utils/ConfigurationUtils.java
+++ b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/utils/ConfigurationUtils.java
@@ -22,7 +22,7 @@ public final class ConfigurationUtils {
         Set<Class<?>> configurations =
                 reflections.getTypesAnnotatedWith(annotation);
         if (configurations.isEmpty())
-            throw new ConfigurationException(annotation.getName() + " not found.");
+            return null;
         if (configurations.size() > 1)
             throw new ConfigurationException(annotation.getName() + " has too many definitions.");
         return configurations.iterator().next();