From f12020c6718e7de28bab125a4608b47f7e38f59b Mon Sep 17 00:00:00 2001
From: Reiner Jung <reiner.jung@email.uni-kiel.de>
Date: Wed, 31 Aug 2022 13:21:53 +0200
Subject: [PATCH] Updated compile results tool, not finished yet.

---
 test.rc                                       |  2 +
 tools/compile-results/build.gradle            |  2 +-
 tools/compile-results/design.rst              | 58 +++++++++++++++
 .../tools/results/CompileResultsMain.java     | 54 ++++++++++++++
 .../tools/results/ElementProducer.java        | 32 ++++++++
 .../tools/results/LogAppenderStage.java       | 66 +++++++++++++++++
 .../tools/results/SummarizeResultsMain.java   | 74 -------------------
 .../tools/results/TeetimeConfiguration.java   | 41 +++++-----
 .../moobench/tools/results/YamlLogSink.java   | 13 ++++
 .../tools/results/YamlReaderStage.java        | 24 ++++++
 .../tools/results/data/Experiment.java        | 38 ++++++++++
 .../tools/results/data/ExperimentLog.java     | 26 +++++++
 .../tools/results/data/Measurements.java      | 63 ++++++++++++++++
 13 files changed, 401 insertions(+), 92 deletions(-)
 create mode 100644 tools/compile-results/design.rst
 create mode 100644 tools/compile-results/src/main/java/moobench/tools/results/CompileResultsMain.java
 create mode 100644 tools/compile-results/src/main/java/moobench/tools/results/ElementProducer.java
 create mode 100644 tools/compile-results/src/main/java/moobench/tools/results/LogAppenderStage.java
 delete mode 100644 tools/compile-results/src/main/java/moobench/tools/results/SummarizeResultsMain.java
 create mode 100644 tools/compile-results/src/main/java/moobench/tools/results/YamlLogSink.java
 create mode 100644 tools/compile-results/src/main/java/moobench/tools/results/YamlReaderStage.java
 create mode 100644 tools/compile-results/src/main/java/moobench/tools/results/data/Experiment.java
 create mode 100644 tools/compile-results/src/main/java/moobench/tools/results/data/ExperimentLog.java
 create mode 100644 tools/compile-results/src/main/java/moobench/tools/results/data/Measurements.java

diff --git a/test.rc b/test.rc
index 87bfb6d..a4b5bfe 100644
--- a/test.rc
+++ b/test.rc
@@ -1,3 +1,5 @@
+MOOBENCH_ARCHIVE="${BASE_DIR}/tools/benchmark/build/distributions/benchmark.tar"
+
 export SLEEP_TIME=10
 export NUM_OF_LOOPS=1
 export THREADS=1
diff --git a/tools/compile-results/build.gradle b/tools/compile-results/build.gradle
index 571174c..95fff6a 100644
--- a/tools/compile-results/build.gradle
+++ b/tools/compile-results/build.gradle
@@ -4,7 +4,7 @@ plugins {
 }
 
 application {
-    mainClass = 'moobench.tools.results.SummarizeResultsMain'
+    mainClass = 'moobench.tools.results.CompileResultsMain'
 }
 
 dependencies {
diff --git a/tools/compile-results/design.rst b/tools/compile-results/design.rst
new file mode 100644
index 0000000..8d88a60
--- /dev/null
+++ b/tools/compile-results/design.rst
@@ -0,0 +1,58 @@
+Compile Results
+===============
+
+Compile results reads in a set of YAML-files, appends them to longer YAML-logs,
+creates a JSON-file over the last N builds and outputs a set of data to be
+displayed in a HTML table.
+
+Parameter
+---------
+
+-i input paths (multiple path)
+-l log path (one path, the individual log paths will be computed from the input paths)
+-w window length in number of builds
+-t path for table
+-j json output
+
+Log Paths
+---------
+
+log_file_path = log path + "/all-" + basename(input path)
+
+Pipeline
+--------
+
+ElementProducer :: yamlInputPathsProducer
+ElementProducer :: yamlLogPathsProducer
+
+YamlReaderStage :: yamlInputReaderStage
+YamlReaderStage :: yamlLogReaderStage
+
+LogAppender :: logAppender
+Distributor :: distributor
+
+YamlLogSink :: yamlLogSink
+ChartAssemblerStage :: chartAssemblerStage
+JsonLogSink :: jsonLogSink
+GenerateHtmlTable :: generateHtmlTable
+FileSink :: fileSink
+
+yamlInputPathsProducer -> yamlInputReaderStage -> logAppender.newRecord
+yamlLogPathsProducer -> yamlLogReaderStage -> logAppender.log
+
+logAppender.output -- log -> distributor
+distributor -> yamlLogSink
+distributor -> chartAssemblerStage -> jsonLogSink
+distributor -> generateHtmlTable -> fileSink
+
+Data Structure
+--------------
+
+Log
+- string name
+- List<Entry> entries
+
+Entry
+- long timestamp
+- Map<String, List<Double>>
+
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/CompileResultsMain.java b/tools/compile-results/src/main/java/moobench/tools/results/CompileResultsMain.java
new file mode 100644
index 0000000..8035cf4
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/CompileResultsMain.java
@@ -0,0 +1,54 @@
+/**
+ * 
+ */
+package moobench.tools.results;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import com.beust.jcommander.JCommander;
+
+import kieker.common.configuration.Configuration;
+import kieker.common.exception.ConfigurationException;
+import kieker.tools.common.AbstractService;
+
+/**
+ * Read the CSV output of the R script and the existing JSON file and append a
+ * record to the JSON file based on the CSV dataset. Further compute a list of
+ * the last 50 runs and the last relative values.
+ *
+ * @author Reiner Jung
+ *
+ */
+public class CompileResultsMain extends AbstractService<TeetimeConfiguration, Settings> {
+
+	 public static void main(final String[] args) {
+		 final CompileResultsMain main = new CompileResultsMain();
+		 System.exit(main.run("compile-result", "Compile Results", args, new Settings()));
+	 }
+	
+	@Override
+	protected TeetimeConfiguration createTeetimeConfiguration() throws ConfigurationException {
+		return new TeetimeConfiguration(this.parameterConfiguration);
+	}
+
+	@Override
+	protected File getConfigurationFile() {
+		return null;
+	}
+
+	@Override
+	protected boolean checkConfiguration(Configuration configuration, JCommander commander) {
+		return true;
+	}
+
+	@Override
+	protected boolean checkParameters(JCommander commander) throws ConfigurationException {
+		return true;
+	}
+
+	@Override
+	protected void shutdownService() {
+	}
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/ElementProducer.java b/tools/compile-results/src/main/java/moobench/tools/results/ElementProducer.java
new file mode 100644
index 0000000..3695517
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/ElementProducer.java
@@ -0,0 +1,32 @@
+/**
+ * 
+ */
+package moobench.tools.results;
+
+import java.util.List;
+
+import teetime.framework.AbstractProducerStage;
+
+/**
+ * @author Reiner Jung
+ * @param <O>
+ * @since 1.3.0
+ *
+ * @param <O> type of the elements
+ */
+public class ElementProducer<O> extends AbstractProducerStage<O> {
+
+	private List<O> elements;
+
+	public ElementProducer(List<O> elements) {
+		this.elements = elements;
+	}
+	
+	@Override
+	protected void execute() throws Exception {
+		for (O element : elements) {
+			this.outputPort.send(element);
+		}
+	}
+
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/LogAppenderStage.java b/tools/compile-results/src/main/java/moobench/tools/results/LogAppenderStage.java
new file mode 100644
index 0000000..0c7f466
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/LogAppenderStage.java
@@ -0,0 +1,66 @@
+/**
+ * 
+ */
+package moobench.tools.results;
+
+import java.util.Map;
+
+import moobench.tools.results.data.Experiment;
+import moobench.tools.results.data.ExperimentLog;
+import teetime.framework.AbstractStage;
+import teetime.framework.InputPort;
+import teetime.framework.OutputPort;
+
+/**
+ * @author Reiner Jung
+ * @since 1.3.0
+ */
+public class LogAppenderStage extends AbstractStage {
+
+	private final InputPort<ExperimentLog> newDataInputPort = this.createInputPort(ExperimentLog.class);
+	private final InputPort<ExperimentLog> logInputPort = this.createInputPort(ExperimentLog.class);
+	private final OutputPort<ExperimentLog> outputPort = this.createOutputPort(ExperimentLog.class);
+	
+	private Map<String,ExperimentLog> logs;
+
+	public InputPort<ExperimentLog> getNewDataInputPort() {
+		return newDataInputPort;
+	}
+	
+	public InputPort<ExperimentLog> getLogInputPort() {
+		return logInputPort;
+	}
+	
+	public OutputPort<ExperimentLog> getOutputPort() {
+		return outputPort;
+	}
+	
+	@Override
+	protected void execute() throws Exception {
+		ExperimentLog newData = this.newDataInputPort.receive();
+		if (newData != null) {
+			appendData(newData);
+		}
+		ExperimentLog logData = this.logInputPort.receive();
+		if (logData != null) {
+			appendData(logData);
+		}
+	}
+	
+	private void appendData(ExperimentLog newData) {
+		ExperimentLog presentLog = logs.get(newData.getKind());
+		if (presentLog != null) {
+			for (Experiment experiment : newData.getExperiments()) {
+				presentLog.getExperiments().add(experiment);
+			}
+		}
+	}
+	
+	@Override
+	protected void onTerminating() {
+		for (ExperimentLog experimentLog : logs.values()) {
+			this.outputPort.send(experimentLog);
+		}
+		super.onTerminating();
+	}
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/SummarizeResultsMain.java b/tools/compile-results/src/main/java/moobench/tools/results/SummarizeResultsMain.java
deleted file mode 100644
index f12a692..0000000
--- a/tools/compile-results/src/main/java/moobench/tools/results/SummarizeResultsMain.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * 
- */
-package moobench.tools.results;
-
-import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-import com.beust.jcommander.JCommander;
-
-import kieker.common.configuration.Configuration;
-import kieker.common.exception.ConfigurationException;
-import kieker.tools.common.AbstractService;
-
-/**
- * Read the CSV output of the R script and the existing JSON file and append a
- * record to the JSON file based on the CSV dataset. Further compute a list of
- * the last 50 runs and the last relative values.
- *
- * @author Reiner Jung
- *
- */
-public class SummarizeResultsMain extends AbstractService<TeetimeConfiguration, Settings> {
-
-	 public static void main(final String[] args) {
-		 final SummarizeResultsMain main = new SummarizeResultsMain();
-		 System.exit(main.run("summarize-result", "Summarize Results", args, new Settings()));
-	 }
-	
-	@Override
-	protected TeetimeConfiguration createTeetimeConfiguration() throws ConfigurationException {
-		return new TeetimeConfiguration(this.parameterConfiguration);
-	}
-
-	@Override
-	protected File getConfigurationFile() {
-		return null;
-	}
-
-	@Override
-	protected boolean checkConfiguration(Configuration configuration, JCommander commander) {
-		return true;
-	}
-
-	@Override
-	protected boolean checkParameters(JCommander commander) throws ConfigurationException {
-		if (!Files.exists(this.parameterConfiguration.getMainLogJson().getParent())) {
-			this.logger.error("Main log does not exist {}", this.parameterConfiguration.getMainLogJson().toString());
-			return false;
-		} else if (!Files.exists(this.parameterConfiguration.getMainLogJson())) {
-			this.logger.info("Main log file does not exist, creating one {}", this.parameterConfiguration.getMainLogJson().toString());
-		}
-		if (!Files.isDirectory(this.parameterConfiguration.getPartialLogJson().getParent())) {
-			this.logger.error("Partial log directory does not exist {}", this.parameterConfiguration.getPartialLogJson().getParent().toString());
-			return false;
-		}
-		for (Path path : parameterConfiguration.getResultCsvPaths()) {
-			if (!Files.exists(this.parameterConfiguration.getMainLogJson())) {
-				this.logger.error("Experiment data file does not exist {}", path.toString());
-				return false;
-			}
-		}
-		if (!Files.exists(this.parameterConfiguration.getMappingFile())) {
-			this.logger.error("Mapping file does not exist {}", this.parameterConfiguration.getMappingFile().toString());
-			return false;
-		}
-		return true;
-	}
-
-	@Override
-	protected void shutdownService() {
-	}
-}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/TeetimeConfiguration.java b/tools/compile-results/src/main/java/moobench/tools/results/TeetimeConfiguration.java
index 68dafd0..8232d5c 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/TeetimeConfiguration.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/TeetimeConfiguration.java
@@ -7,6 +7,7 @@ import java.util.Map;
 
 import com.fasterxml.jackson.databind.JsonNode;
 
+import moobench.tools.results.data.ExperimentLog;
 import teetime.framework.Configuration;
 import teetime.stage.basic.distributor.Distributor;
 import teetime.stage.basic.distributor.strategy.CopyByReferenceStrategy;
@@ -21,22 +22,28 @@ public class TeetimeConfiguration extends Configuration {
 			
 		ElementProducer<Path> yamlInputPathsProducer = new ElementProducer<>(settings.getInputPaths());
 		ElementProducer<Path> yamlLogPathsProducer = new ElementProducer<>(logFilePaths);
-
-		LogAppender :: logAppender
-		Distributor :: distributor
-
-		YamlLogSink :: yamlLogSink
-		ChartAssemblerStage :: chartAssemblerStage
-		JsonLogSink :: jsonLogSink
-		GenerateHtmlTable :: generateHtmlTable
-		FileSink :: fileSink
-
-		yamlInputPathsProducer -> logAppender.newRecord
-		yamlLogPathsProducer -> logAppender.log
-
-		logAppender.output -- log -> distributor
-		distributor -> yamlLogSink
-		distributor -> chartAssemblerStage -> jsonLogSink
-		distributor -> generateHtmlTable -> fileSink
+		
+		YamlReaderStage yamlInputReader = new YamlReaderStage();
+		YamlReaderStage yamlLogReader = new YamlReaderStage();
+
+		LogAppenderStage logAppenderStage = new LogAppenderStage();
+		Distributor<ExperimentLog> distributor = new Distributor<>(new CopyByReferenceStrategy());
+
+		YamlLogSink yamlLogSink = new YamlLogSink();
+		
+		//ChartAssemblerStage :: chartAssemblerStage
+		//JsonLogSink :: jsonLogSink
+		//GenerateHtmlTable :: generateHtmlTable
+		//FileSink :: fileSink
+
+		this.connectPorts(yamlInputPathsProducer.getOutputPort(), yamlInputReader.getInputPort());
+		this.connectPorts(yamlLogPathsProducer.getOutputPort(), yamlLogReader.getInputPort());
+		
+		this.connectPorts(yamlInputReader.getOutputPort(), logAppenderStage.getNewDataInputPort());
+		this.connectPorts(yamlLogReader.getOutputPort(), logAppenderStage.getLogInputPort());
+		
+		this.connectPorts(logAppenderStage.getOutputPort(), distributor.getInputPort());
+		
+		this.connectPorts(distributor.getNewOutputPort(), yamlLogSink.getInputPort());
 	}
 }
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/YamlLogSink.java b/tools/compile-results/src/main/java/moobench/tools/results/YamlLogSink.java
new file mode 100644
index 0000000..7603550
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/YamlLogSink.java
@@ -0,0 +1,13 @@
+package moobench.tools.results;
+
+import moobench.tools.results.data.ExperimentLog;
+import teetime.framework.AbstractConsumerStage;
+
+public class YamlLogSink extends AbstractConsumerStage<ExperimentLog> {
+
+	@Override
+	protected void execute(ExperimentLog element) throws Exception {
+		// TODO Auto-generated method stub
+	}
+
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/YamlReaderStage.java b/tools/compile-results/src/main/java/moobench/tools/results/YamlReaderStage.java
new file mode 100644
index 0000000..e64b2e5
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/YamlReaderStage.java
@@ -0,0 +1,24 @@
+package moobench.tools.results;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+import moobench.tools.results.data.ExperimentLog;
+import teetime.stage.basic.AbstractTransformation;
+
+public class YamlReaderStage extends AbstractTransformation<Path, ExperimentLog> {
+
+	@Override
+	protected void execute(Path path) throws Exception {
+		Yaml yaml = new Yaml(new Constructor(ExperimentLog.class));
+		InputStream inputStream = Files.newInputStream(path);
+		ExperimentLog data = yaml.load(inputStream);
+		
+		this.outputPort.send(data);
+	}
+
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/data/Experiment.java b/tools/compile-results/src/main/java/moobench/tools/results/data/Experiment.java
new file mode 100644
index 0000000..d08c2dc
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/data/Experiment.java
@@ -0,0 +1,38 @@
+/**
+ * 
+ */
+package moobench.tools.results.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Reiner Jung
+ *
+ */
+public class Experiment {
+
+	double timestamp;
+	Map<String,Measurements> measurements = new HashMap<>();
+	
+	public double getTimestamp() {
+		return timestamp;
+	}
+	
+	public void setTimestamp(double timestamp) {
+		this.timestamp = timestamp;
+	}
+	
+	public Map<String,Measurements> getMeasurements() {
+		return measurements;
+	}
+	public void setMeasurements(Map<String,Measurements> measurements) {
+		this.measurements = measurements;
+	}
+	
+	@Override
+	public String toString() {
+		return String.format("time: %f, measurements: %d\n", timestamp, measurements.size());
+	}
+	
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/data/ExperimentLog.java b/tools/compile-results/src/main/java/moobench/tools/results/data/ExperimentLog.java
new file mode 100644
index 0000000..e619816
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/data/ExperimentLog.java
@@ -0,0 +1,26 @@
+package moobench.tools.results.data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ExperimentLog {
+	
+	String kind;
+	List<Experiment> experiments = new ArrayList<>();
+	
+	public String getKind() {
+		return kind;
+	}
+	
+	public void setKind(String kind) {
+		this.kind = kind;
+	}
+	
+	public List<Experiment> getExperiments() {
+		return experiments;
+	}
+
+	public void setExperiments(List<Experiment> experiments) {
+		this.experiments = experiments;
+	}
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/data/Measurements.java b/tools/compile-results/src/main/java/moobench/tools/results/data/Measurements.java
new file mode 100644
index 0000000..e6d1dc8
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/data/Measurements.java
@@ -0,0 +1,63 @@
+package moobench.tools.results.data;
+
+public class Measurements {
+		
+	private double mean;
+	private double convidence;
+	private double standardDeviation;
+	private double lowerQuartile;
+	private double median;
+	private double upperQuartile;
+	private double max;
+	private double min;
+
+	public Measurements(double mean, double standardDeviation, double convidence, double lowerQuartile, double median, double upperQuartile, double min, double max) {
+		this.mean = mean;
+		this.convidence = convidence;
+		this.standardDeviation = standardDeviation;
+		this.lowerQuartile = lowerQuartile;
+		this.median = median;
+		this.upperQuartile = upperQuartile;
+		this.min = min;
+		this.max = max;
+	}
+	
+	public double getMean() {
+		return mean;
+	}
+	
+	/**
+	 * Returns the convidence value, to get the convidence interval you need to compute the interval as
+	 * [mean-convidence:mean+convidence]
+	 * 
+	 * @return convidence value
+	 */
+	public double getConvidence() {
+		return convidence;
+	}
+	
+	public double getStandardDeviation() {
+		return standardDeviation;
+	}
+	
+	public double getLowerQuartile() {
+		return lowerQuartile;
+	}
+	
+	public double getMedian() {
+		return median;
+	}
+	
+	public double getUpperQuartile() {
+		return upperQuartile;
+	}
+	
+	public double getMin() {
+		return min;
+	}
+	
+	public double getMax() {
+		return max;
+	}
+
+}
-- 
GitLab