diff --git a/src/report/DataSyncReport.java b/src/report/DataSyncReport.java index 1fde09e235c5cd31357d5c38070d1d8490017744..573f23aa2b7dab651a046d364021d23515a29053 100644 --- a/src/report/DataSyncReport.java +++ b/src/report/DataSyncReport.java @@ -127,6 +127,7 @@ public class DataSyncReport extends SamplingReport{ //Write out statistics gathered over all hosts with database write("sim_time: " + format(getSimTime()) +", "+ "avg_used_mem: " + getAverage(usedDataBasePercentage) +"%, "+ + "min_used_mem: " + getMinimum(usedDataBasePercentage) +"%, "+ "max_used_mem: " + getMaximum(usedDataBasePercentage) +"%, "+ "med_avg_data_util: " + getMedian(averageDataUtility)+ ", "+ "avg_data_util: " + getAverage(averageDataUtility) + ", "+ diff --git a/src/report/Report.java b/src/report/Report.java index 1b9be30127baa6e46572ce35c341d9fe89fbe604..479e69888737a25cf797301b667ef0028886e107 100644 --- a/src/report/Report.java +++ b/src/report/Report.java @@ -414,6 +414,21 @@ public abstract class Report { return format(max); } + /** + * Returns the minimum of the values in the list + * as a formatted string with the given numerical precision. + * Return "NaN" for empty lists. + * + * @param values the list to search the minimum in + * @return a formatted string of the minimum in the list + */ + public String getMinimum(List<Double> values){ + if (values.isEmpty()){ + return NAN; + } + double min = Collections.min(values); + return format(min); + } /** * Returns the variance of the values in the List. * diff --git a/toolkit/reportSummary/dataSyncAnalysis.py b/toolkit/reportSummary/dataSyncAnalysis.py index 0cae787ac5343627fd55376813926164e1bd32f8..f714e522849e5dda85b6ee434f5538392a8aa1d2 100644 --- a/toolkit/reportSummary/dataSyncAnalysis.py +++ b/toolkit/reportSummary/dataSyncAnalysis.py @@ -15,10 +15,10 @@ import matplotlib.ticker as ticker # (2) a path to save the resulting graphic to. # # Data sync stats for scenario realisticScenario -# sim_time: 60.00, avg_used_mem: 0.00%, max_used_mem: 0.00%, med_avg_data_util: 0.99, avg_data_util: 0.99, med_avg_data_age: 21.15, avg_data_age: 24.56, med_max_data_age: 21.15, med_avg_data_dist: 97.41, avg_data_dist: 90.05, med_max_data_dist: 97.41 +# sim_time: 60.00, avg_used_mem: 0.00%, min_used_mem: 0.00%, max_used_mem: 0.00%, med_avg_data_util: 0.99, avg_data_util: 0.99, med_avg_data_age: 21.15, avg_data_age: 24.56, med_max_data_age: 21.15, med_avg_data_dist: 97.41, avg_data_dist: 90.05, med_max_data_dist: 97.41 # avg_ratio_map: 0.00%, avg_ratio_marker: 29.41%, avg_ratio_skill: 47.06%, avg_ratio_res: 23.53% # -# sim_time: 120.10, avg_used_mem: 0.00%, max_used_mem: 0.00%, med_avg_data_util: 0.99, avg_data_util: 0.98, med_avg_data_age: 42.55, avg_data_age: 54.16, med_max_data_age: 42.55, med_avg_data_dist: 117.17, avg_data_dist: 146.08, med_max_data_dist: 117.17 +# sim_time: 120.10, avg_used_mem: 0.00%, min_used_mem: 0.00%, max_used_mem: 0.00%, med_avg_data_util: 0.99, avg_data_util: 0.98, med_avg_data_age: 42.55, avg_data_age: 54.16, med_max_data_age: 42.55, med_avg_data_dist: 117.17, avg_data_dist: 146.08, med_max_data_dist: 117.17 # avg_ratio_map: 0.00%, avg_ratio_marker: 23.64%, avg_ratio_skill: 32.73%, avg_ratio_res: 43.64% # ... @@ -30,6 +30,7 @@ def main(analysisFileName, graphicFileName): # Interpret lines to find memory consumption, data utility, data distance and data age metrics over time timePoints = [] averageMemoryConsumption = [] + minimumMemoryConsumption = [] maximumMemoryConsumption = [] medianAverageDataUtility = [] averageAverageDataUtility = [] @@ -42,7 +43,7 @@ def main(analysisFileName, graphicFileName): nextTimePoint = 0 for line in report: match = re.match("sim_time: (\d+.\d+), " - "avg_used_mem: (\d+.\d+)%, ""max_used_mem: (\d+.\d+)%, " + "avg_used_mem: (\d+.\d+)%, min_used_mem: (\d+.\d+)%, max_used_mem: (\d+.\d+)%, " "med_avg_data_util: (\d+.\d+), avg_data_util: (\d+.\d+), " "med_avg_data_age: (\d+.\d+), avg_data_age: (\d+.\d+), med_max_data_age: (\d+.\d+), " "med_avg_data_dist: (\d+.\d+), avg_data_dist: (\d+.\d+), med_max_data_dist: (\d+.\d+)", line) @@ -57,15 +58,16 @@ def main(analysisFileName, graphicFileName): # Make sure to use correct unit (minutes, kilometres) timePoints.append(timePoint) averageMemoryConsumption.append(float(match.group(2))) - maximumMemoryConsumption.append(float(match.group(3))) - medianAverageDataUtility.append(float(match.group(4))) - averageAverageDataUtility.append(float(match.group(5))) - medianAverageDataAge.append(float(match.group(6)) / 60) - averageAverageDataAge.append(float(match.group(7)) / 60) - medianMaximumDataAge.append(float(match.group(8)) / 60) - medianAverageDataDistance.append(float(match.group(9)) / 1000) - averageAverageDataDistance.append(float(match.group(10)) / 1000) - medianMaximumDataDistance.append(float(match.group(11)) / 1000) + minimumMemoryConsumption.append(float(match.group(3))) + maximumMemoryConsumption.append(float(match.group(4))) + medianAverageDataUtility.append(float(match.group(5))) + averageAverageDataUtility.append(float(match.group(6))) + medianAverageDataAge.append(float(match.group(7)) / 60) + averageAverageDataAge.append(float(match.group(8)) / 60) + medianMaximumDataAge.append(float(match.group(9)) / 60) + medianAverageDataDistance.append(float(match.group(10)) / 1000) + averageAverageDataDistance.append(float(match.group(11)) / 1000) + medianMaximumDataDistance.append(float(match.group(12)) / 1000) # Create four graphics over time: one each for memory consumption, data utility, data distance and data age fig = plt.figure(figsize=(12,12)) @@ -88,7 +90,9 @@ def main(analysisFileName, graphicFileName): addSubplot(3, title='Memory Consumption', ylabel='Used memory', - plots=[(averageMemoryConsumption, 'Average'), (maximumMemoryConsumption, 'Maximum')]) + plots=[(averageMemoryConsumption, 'Average'), + (maximumMemoryConsumption, 'Maximum'), + (minimumMemoryConsumption, 'Minimum')]) addSubplot(2, title='Average Data Utility in Local Database', ylabel='Average data utility', plots=[(medianAverageDataUtility, 'Median'), (averageAverageDataUtility, 'Average')])