diff --git a/build.gradle b/build.gradle index 629e5bd35f8068eae889f10d3c30ca2d2d05213d..3c9a22f9a3d570b9ca88f0e6764ecd22149e7915 100644 --- a/build.gradle +++ b/build.gradle @@ -142,6 +142,7 @@ dependencies { runtime 'ch.qos.logback:logback-classic:1+' testCompile 'org.testng:testng:6+' + testCompile 'net.sf.jchart2d:jchart2d:3+' // testCompile 'org.apache.jmeter:ApacheJMeter:2.+' } diff --git a/src/test/java/it/unibz/inf/isochrone/network/AlgorithmRuntimeTest.java b/src/test/java/it/unibz/inf/isochrone/network/AlgorithmRuntimeTest.java index 2018a9cecd35941b8488c6c8e6dc2b389b0b37f3..0e3ad513b884d645789e7d3d1aca2b6527727c55 100644 --- a/src/test/java/it/unibz/inf/isochrone/network/AlgorithmRuntimeTest.java +++ b/src/test/java/it/unibz/inf/isochrone/network/AlgorithmRuntimeTest.java @@ -1,5 +1,10 @@ package it.unibz.inf.isochrone.network; +import info.monitorenter.gui.chart.Chart2D; +import info.monitorenter.gui.chart.IAxis; +import info.monitorenter.gui.chart.IAxis.AxisTitle; +import info.monitorenter.gui.chart.ITrace2D; +import info.monitorenter.gui.chart.traces.Trace2DSimple; import it.unibz.inf.isochrone.algorithm.Isochrone; import it.unibz.inf.isochrone.algorithm.MDijkstra; import it.unibz.inf.isochrone.algorithm.MineX; @@ -8,6 +13,9 @@ import it.unibz.inf.isochrone.config.ConfigDataset; import it.unibz.inf.isochrone.util.EnumContainer.Direction; import it.unibz.inf.isochrone.util.EnumContainer.Mode; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Stroke; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; @@ -25,6 +33,8 @@ import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; +import javax.imageio.ImageIO; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.AfterClass; @@ -42,6 +52,7 @@ public final class AlgorithmRuntimeTest { private static final int REPEAT_COUNT = 5; private static final String RESULTFILE_ENCODING = "UTF-8"; private static final String RESULTFILE_CSV_RUNTIME = "build/reports/tests/algorithm-runtimes.csv"; + private static final String RESULTFILE_PNG_RUNTIME = "build/reports/tests/algorithm-runtimes.png"; private static final String RESULTFILE_XML_RUNTIME = "build/reports/tests/algorithm-runtimes.xml"; private static final int[] RUNTIME_OFFSETS = { 60, // 1 minute (in sec) @@ -105,8 +116,9 @@ public final class AlgorithmRuntimeTest { @AfterClass public void writeRuntimes() { - writeRuntimeXML(); writeRuntimeCSV(); + writeRuntimePNG(); + writeRuntimeXML(); } @BeforeClass(alwaysRun = true) @@ -257,7 +269,7 @@ public final class AlgorithmRuntimeTest { final Set<Entry<String, Long>> timeSet = results.entrySet(); final Iterator<Entry<String, Long>> iter = timeSet.iterator(); while (iter.hasNext()) { - fw.write(String.valueOf(iter.next().getValue().longValue() / repeatCount)); + fw.write(String.valueOf(iter.next().getValue().longValue() / (double) repeatCount)); if (iter.hasNext()) { fw.write(separator); } @@ -271,6 +283,72 @@ public final class AlgorithmRuntimeTest { } } + private static void writeMapToPNG(final File file, final Set<Entry<String, Map<String, Long>>> resultSet, final int repeatCount) { + final int nrAlgorithms = resultSet.iterator().next().getValue().size(); + + final Map<String, ITrace2D> traceMap = new HashMap<>(nrAlgorithms); + final Stroke stroke = new BasicStroke(3); + final Chart2D chart = new Chart2D(); + + final IAxis<?> axisX = chart.getAxisX(); + axisX.setAxisTitle(new AxisTitle("Isochrone runtime (sec)")); + + final IAxis<?> axisY = chart.getAxisY(); + axisY.setAxisTitle(new AxisTitle("Time (msec)")); + axisY.setPaintGrid(true); + + // Create colors + final Color[] colorArr = new Color[nrAlgorithms]; + for (int i = 0; i < nrAlgorithms; ++i) { + // CHECKSTYLE:OFF MagicNumber + colorArr[i] = Color.getHSBColor((float) i / (float) nrAlgorithms, 0.85f, 1.0f); + // CHECKSTYLE:ON MagicNumber + } + + int nrAlgorithm = 0; + for (final Entry<String, Map<String, Long>> runtimeEntry : resultSet) { + final String time = runtimeEntry.getKey(); + final Map<String, Long> results = runtimeEntry.getValue(); + + double dmax = -1; + try { + dmax = Float.parseFloat(time); + } catch (final NumberFormatException e) { + // runtime is not a number (most likely it is something like summed values... summed times will not be plotted) + continue; + } + + if (dmax > RUNTIME_OFFSETS[1]) { + // only plot runtimes until first offset (because of axis scaling issues) + break; + } + + final Set<Entry<String, Long>> timeSet = results.entrySet(); + for (final Entry<String, Long> entry : timeSet) { + final String algorithmName = entry.getKey(); + final double runtime = entry.getValue().longValue() / (double) repeatCount; + + ITrace2D trace = traceMap.get(algorithmName); + if (trace == null) { + trace = new Trace2DSimple(algorithmName); + trace.setColor(colorArr[nrAlgorithm++]); + trace.setStroke(stroke); + traceMap.put(algorithmName, trace); + + chart.addTrace(trace); + } + + trace.addPoint(dmax, runtime); + } + } + + try { + ImageIO.write(chart.snapShot(), "png", new File(RESULTFILE_PNG_RUNTIME)); + } catch (final IOException e) { + e.printStackTrace(); + } + } + private static void writeMapToXML(final File file, final Set<Entry<String, Map<String, Long>>> resultSet, final int repeatCount) { try (final BufferedWriter fw = new BufferedWriter(new PrintWriter(file, RESULTFILE_ENCODING))) { fw.write("<?xml version=\"1.0\" encoding=\"" + RESULTFILE_ENCODING + "\"?>"); @@ -286,7 +364,9 @@ public final class AlgorithmRuntimeTest { fw.newLine(); final Set<Entry<String, Long>> timeSet = results.entrySet(); for (final Entry<String, Long> entry : timeSet) { - fw.write("\t\t<" + entry.getKey() + ">" + entry.getValue().longValue() / repeatCount + "</" + entry.getKey() + ">"); + final String algorithmName = entry.getKey(); + final double runtime = entry.getValue().longValue() / (double) repeatCount; + fw.write("\t\t<" + algorithmName + ">" + runtime + "</" + algorithmName + ">"); fw.newLine(); } fw.write("\t</time_" + time + ">"); @@ -305,6 +385,11 @@ public final class AlgorithmRuntimeTest { writeMapToCSV(new File(RESULTFILE_CSV_RUNTIME), resultSet, REPEAT_COUNT); } + private static void writeRuntimePNG() { + final Set<Entry<String, Map<String, Long>>> resultSet = runtimes.entrySet(); + writeMapToPNG(new File(RESULTFILE_CSV_RUNTIME), resultSet, REPEAT_COUNT); + } + private static void writeRuntimeXML() { final Set<Entry<String, Map<String, Long>>> resultSet = runtimes.entrySet(); writeMapToXML(new File(RESULTFILE_XML_RUNTIME), resultSet, REPEAT_COUNT);