Details
diff --git a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/Apdex.java b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/Apdex.java
index fc10a8f..d08ba89 100644
--- a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/Apdex.java
+++ b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/Apdex.java
@@ -23,4 +23,8 @@ public class Apdex {
public long getN() {
return n;
}
+
+ public double getApdexMetric(){
+ return 1 - ((getSatisfied() + 0.5 * getTolerated()) / getN());
+ }
}
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 94bcce7..0066458 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
@@ -11,13 +11,19 @@ import java.util.concurrent.ConcurrentHashMap;
public class FrequencyDataSet {
private Map<Granularity, Integer> granularityPopulation = new ConcurrentHashMap<>();
+ private SummaryStatistics statistics = new SummaryStatistics();
private long n;
- public void addItem(Granularity item) {
+ public void addItem(Granularity item, double executionTime) {
granularityPopulation.put(item, granularityPopulation.getOrDefault(item, 0) + 1);
+ statistics.addValue(executionTime);
n++;
}
+ public double getMeanExecutionTime(){
+ return statistics.getMean();
+ }
+
public long getTotalItems(){
return n;
}
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
new file mode 100644
index 0000000..c49e89b
--- /dev/null
+++ b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/MonitoringCycle.java
@@ -0,0 +1,25 @@
+package br.ufrgs.inf.prosoft.tigris.sampling;
+
+public class MonitoringCycle {
+ private double averageProcTimesSample;
+ private double averageProcTimesPopulation;
+ private double sampleSize;
+ private double populationSize;
+
+ public MonitoringCycle(double averageProcTimesSample, double averageProcTimesPopulation, double sampleSize, double populationSize) {
+ this.averageProcTimesSample = averageProcTimesSample;
+ this.averageProcTimesPopulation = averageProcTimesPopulation;
+ this.sampleSize = sampleSize;
+ this.populationSize = populationSize;
+ }
+
+ @Override
+ public String toString() {
+ return "MonitoringCycle{" +
+ "averageProcTimesSample=" + averageProcTimesSample +
+ ", averageProcTimesPopulation=" + averageProcTimesPopulation +
+ ", sampleSize=" + sampleSize +
+ ", populationSize=" + populationSize +
+ '}';
+ }
+}
diff --git a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/PerformanceBaselineDataSet.java b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/PerformanceBaselineDataSet.java
index 2ab10b1..eb40cde 100644
--- a/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/PerformanceBaselineDataSet.java
+++ b/tigris/src/main/java/br/ufrgs/inf/prosoft/tigris/sampling/PerformanceBaselineDataSet.java
@@ -18,6 +18,7 @@ public class PerformanceBaselineDataSet {
private Map<Granularity, DescriptiveStatistics> granularityBaseline = new ConcurrentHashMap<>();
private DescriptiveStatistics overallBaseline = new DescriptiveStatistics(1200);
+ private DescriptiveStatistics historicOfBaselines = new DescriptiveStatistics(1200);
private int n = 0;
public void addItem(Granularity item, long executionTime) {
@@ -29,40 +30,32 @@ public class PerformanceBaselineDataSet {
overallBaseline.addValue(executionTime);
}
- //TODO compare baseline againts baseline, not against sampled items
- //Solução 1: Guarda o baseline com a média mais baixa de todas - em teoria esse é o mais próximo da aplicação "real", sem influencia de monitoração ou falta de recursos - mínimo global
- //compara o sample com o minimo global
-
- //need to detect global max and min to avoid "getting used" to bad things
- //diminuir as rodadas de baseline (espaços maiores), guardar max and min, olhar pra quartis talvez?
- //se o q1 ta ficando maior, significa que a carga e overhead estão subindo, se está menor, está caindo
- //questões: a aplicação está ok sem monitoração? essa é a melhor performance dela? é a pior? o quao distante dos topos está
//não comparar baseline com sample, não faz sentido - ou é sample com sample, ou é baseline com sample
- //baseline com sample, diz o overhead do sampling
- //baseline com baseline diz a carga da aplicação
+ //comparar baseline com sample, diz o overhead do sampling
+ //comparar baseline com baseline histórico diz a carga da aplicação
+ public boolean isAppStruggling() {
+ historicOfBaselines.addValue(overallBaseline.getMean());
+
+ return historicOfBaselines.getPercentile(50) < overallBaseline.getMean();
+ }
+
+
public Apdex getApdexResultsPerEvent(Map<Granularity, DescriptiveStatistics> sampledDataSet) {
long satisfied = 0, tolerated = 0, n = 0;
for (Map.Entry<Granularity, DescriptiveStatistics> baselineEntry : granularityBaseline.entrySet()) {
DescriptiveStatistics stats = baselineEntry.getValue();
double mean = stats.getMean();
double std = stats.getStandardDeviation();
- if (stats.getN() == stats.getWindowSize()) {
- mean = new Mean().evaluate(stats.getValues(), weights);
- std = FastMath.sqrt(new Variance().evaluate(stats.getValues(), weights));
- }
+// if (stats.getN() == stats.getWindowSize()) {
+// mean = new Mean().evaluate(stats.getValues(), weights);
+// std = FastMath.sqrt(new Variance().evaluate(stats.getValues(), weights));
+// }
double meanPlusStd = mean + std;
DescriptiveStatistics descriptiveStatistics = sampledDataSet.get(baselineEntry.getKey());
if (descriptiveStatistics == null)
continue;
for (double value : descriptiveStatistics.getValues()) {
-// if (value <= mean) {
-// satisfied++;
-// }
-// if (value > mean &&
-// value < meanPlusStd) {
-// tolerated++;
-// }
if (value <= meanPlusStd) {
satisfied++;
}
@@ -74,6 +67,41 @@ public class PerformanceBaselineDataSet {
}
}
return new Apdex(satisfied, tolerated, n);
+
+
+// long satisfied = 0, tolerated = 0, n = 0;
+// for (Map.Entry<Granularity, DescriptiveStatistics> baselineEntry : granularityBaseline.entrySet()) {
+// DescriptiveStatistics stats = baselineEntry.getValue();
+// double mean = stats.getMean();
+// double std = stats.getStandardDeviation();
+//// if (stats.getN() == stats.getWindowSize()) {
+//// mean = new Mean().evaluate(stats.getValues(), weights);
+//// std = FastMath.sqrt(new Variance().evaluate(stats.getValues(), weights));
+//// }
+//
+// double meanPlusStd = mean + std;
+// DescriptiveStatistics descriptiveStatistics = sampledDataSet.get(baselineEntry.getKey());
+// if (descriptiveStatistics == null)
+// continue;
+// for (double value : descriptiveStatistics.getValues()) {
+//// if (value <= mean) {
+//// satisfied++;
+//// }
+//// if (value > mean &&
+//// value < meanPlusStd) {
+//// tolerated++;
+//// }
+// if (value <= meanPlusStd) {
+// satisfied++;
+// }
+// if (value > meanPlusStd &&
+// value < mean + (2 * std)) {
+// tolerated++;
+// }
+// n++;
+// }
+// }
+// return new Apdex(satisfied, tolerated, n);
}
/**
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 3a5b3c0..c2ec0a9 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
@@ -31,7 +31,6 @@ public class Sampling {
private ExponentialDecayFunction decayingPrecision;
private FrequencyDataSet population = new FrequencyDataSet(), sample = new FrequencyDataSet();
private PerformanceBaselineDataSet performanceBaselineDataSet = new PerformanceBaselineDataSet();
- private Map<Granularity, DescriptiveStatistics> lowestPerformanceBaselineDataSet = new ConcurrentHashMap<>();
private Map<Granularity, DescriptiveStatistics> sampledDataSet = new ConcurrentHashMap<>();
//PBA history
@@ -70,7 +69,7 @@ public class Sampling {
public boolean samplingDecision(Granularity granularity, long executionTime) {
if (population.getTotalItems() == 0)
startTime = System.currentTimeMillis();
- population.addItem(granularity);
+ population.addItem(granularity, executionTime);
if (performanceBaselineEnabled) {
return false;
@@ -109,44 +108,51 @@ public class Sampling {
synchronized (samplingRateLock) {
if (this.sampledDataSet.isEmpty()) {
logger.info("No sampled data, doing nothing...");
- //if no impact, increase by 1%
-// samplingRate += 0.01;
-//
-// if (samplingRate > 1)
-// samplingRate = 1;
-//
-// logger.info("New sampling rate: {}", samplingRate);
-// this.resetSamplingDistribution();
+// if no impact, increase by 1%
+ samplingRate += 0.01;
+
+ if (samplingRate > 1)
+ samplingRate = 1;
+
+ logger.info("New sampling rate: {}", samplingRate);
+ this.resetSamplingDistribution();
return;
}
-// this.performanceBaselineDataSet.
-//
-// lowestPerformanceBaselineDataSet
// Apdex apdex = this.performanceBaselineDataSet.getApdexResults(this.sampledDataSet, this.lastSampledTimes);
+// double baselineImpact = performanceBaselineDataSet.getBaselineImpactedByWorkload();
Apdex apdex = this.performanceBaselineDataSet.getApdexResultsPerEvent(this.sampledDataSet);
- double impact = 1 - ((apdex.getSatisfied() + 0.5 * apdex.getTolerated()) / apdex.getN());
-
- //if we have just 1 tolerated, the impact will not be zero anymore
- if (impact <= 0.1) {
- logger.info("No monitoring impact detected: {}, increasing the sampling rate...", impact);
- //if no impact, increase by 10%
- samplingRate += 0.1;
- } else
- //otherwise stays the same - not necessary here
- if (impact > 0.1 && impact <= 0.2) {
- logger.info("Minimal monitoring impact detected: {}, keeping it the same...", impact);
- } else if (impact > 0.2) {
- double reduction = impact - 0.2;
- logger.info("Monitoring impact detected: {}, decreasing the current sampling rate {} by {}%", impact, samplingRate, reduction);
-// logger.info("{}, {}, {}", apdex.getSatisfied(), apdex.getTolerated(), apdex.getN());
-// logger.info("{}", this.performanceBaselineDataSet.getOverallAvg());
-// logger.info("{}", this.performanceBaselineDataSet.getOverallStd());
-// logger.info("{}", this.performanceBaselineDataSet.getTotalItems());
-
- //reduce by the amount of overhead
- samplingRate = samplingRate - (samplingRate * (reduction / 1d));
- }
+ double impact = (1 - ((apdex.getSatisfied() + 0.5 * apdex.getTolerated()) / apdex.getN()));
+
+ if (!this.performanceBaselineDataSet.isAppStruggling()) {
+
+ logger.info("App is not struggling, increasing the current sampling rate {} by {}%", samplingRate, impact);
+ samplingRate += impact;
+
+// //if we have just 1 tolerated, the impact will not be zero anymore
+// if (impact <= 0.1) {
+// logger.info("No monitoring impact detected: {}, increasing the sampling rate...", impact);
+// //if no impact, increase by 10%
+// samplingRate += 0.1;
+// } else
+// //otherwise stays the same - not necessary here
+// if (impact > 0.1 && impact <= 0.2) {
+// logger.info("Minimal monitoring impact detected: {}, keeping it the same...", impact);
+// } else if (impact > 0.2) {
+// double reduction = impact - 0.2;
+// logger.info("Monitoring impact detected: {}, decreasing the current sampling rate {} by {}%", impact, samplingRate, reduction);
+//// logger.info("{}, {}, {}", apdex.getSatisfied(), apdex.getTolerated(), apdex.getN());
+//// logger.info("{}", this.performanceBaselineDataSet.getOverallAvg());
+//// logger.info("{}", this.performanceBaselineDataSet.getOverallStd());
+//// logger.info("{}", this.performanceBaselineDataSet.getTotalItems());
+//
+// //reduce by the amount of overhead
+// samplingRate = samplingRate - (samplingRate * (reduction / 1d));
+// }
+ } else { //app is struggling
+ logger.info("App is struggling, decreasing the current sampling rate {} by {}%", samplingRate, impact);
+ samplingRate -= impact;
+ }
if (samplingRate < 0)
samplingRate = 0;
@@ -166,14 +172,12 @@ public class Sampling {
}
}
- DescriptiveStatistics lastSampledTimes = new DescriptiveStatistics(1200);
- public void addSampledItem(Granularity granularity, long startTime) {
- sample.addItem(granularity);
+// DescriptiveStatistics lastSampledTimes = new DescriptiveStatistics(1200);
+ public void addSampledItem(Granularity granularity, long executionTime) {
+ sample.addItem(granularity, executionTime);
DescriptiveStatistics statistics = sampledDataSet.getOrDefault(granularity, new DescriptiveStatistics());
- long time = System.nanoTime() - startTime;
- statistics.addValue(time);
- lastSampledTimes.addValue(time);
+ statistics.addValue(executionTime);
sampledDataSet.put(granularity, statistics);
}
@@ -262,10 +266,15 @@ public class Sampling {
logger.info("Monitoring is reset...");
}
- public void endMonitoringCycle() {
- logger.info("Adaptive Sampling Monitoring Cycle Finished - Sample traces: {}", getSample().getTotalItems());
- logger.info("Adaptive Sampling Monitoring Cycle Finished - Population traces: {}", getPopulation().getTotalItems());
+ public MonitoringCycle endMonitoringCycle() {
+ MonitoringCycle monitoringCycle = new MonitoringCycle(
+ getSample().getMeanExecutionTime(),
+ getPopulation().getMeanExecutionTime(),
+ getSample().getTotalItems(),
+ getPopulation().getTotalItems());
+ logger.info("Adaptive Sampling Monitoring Cycle Finished: {}", monitoringCycle);
startMonitoringCycle();
+ return monitoringCycle;
}
private Long minimumSampleSize;
@@ -282,7 +291,7 @@ public class Sampling {
return;
}
- double chance = new BinomialDistribution(1, 0.3d).sample();
+ double chance = new BinomialDistribution(1, 0.1d).sample();
if (chance == 1) {
minimumSampleSize = getMinimumSampleSize(this.population.getTotalItems());
if (minimumSampleSize > 0) {
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 32bb6b0..2eaeef6 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
@@ -86,17 +86,17 @@ public class SamplingAspect implements Runnable {
return result;
}
- boolean decision = sampling.samplingDecision(granularity, 0);
+ boolean decision = sampling.samplingDecision(granularity, endTime - startTime);
if (decision)
- sampling.addSampledItem(granularity, startTime);
+ sampling.addSampledItem(granularity, nanoTime() - startTime);
}
return result;
}
static List<Double> samplingRates = new ArrayList<>();
- static int numberOfCycles = 0;
+ static List<MonitoringCycle> cycles = new ArrayList<>();
@Override
public void run() {
@@ -106,14 +106,13 @@ public class SamplingAspect implements Runnable {
if (!sampling.isPerformanceBaselineEnabled() && sampling.isReady()) {
logger.info("Sample is ready, releasing for analysis and resetting...");
- sampling.endMonitoringCycle();
- numberOfCycles++;
+ cycles.add(sampling.endMonitoringCycle());
}
}
}
public static void printResults(){
logger.info("Sampling Rates: {}", samplingRates);
- logger.info("Number of finished cycles: {}", numberOfCycles);
+ logger.info("Finished cycles {}: {}", cycles.size(), cycles);
}
}
\ No newline at end of file