Java tutorial
/* * Copyright 2015 by Thomas Lottermann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package notaql.performance; import notaql.NotaQL; import org.apache.commons.cli.*; import org.json.JSONArray; import org.json.JSONObject; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.*; import java.time.Duration; import java.time.Instant; import java.util.*; import java.util.stream.Collectors; import java.util.stream.StreamSupport; /** * TODO: The mongodb collections must be compacted before running performance tests! */ public class PerformanceTest { private static final String BASE_PATH = "/performanceTest/tests"; private static final int RUNS = 5; private static String inEngine = null; private static String outEngine = null; private static String testCase = null; public static void main(String... args) throws IOException, URISyntaxException, ParseException { final Options options = new Options(); options.addOption("c", "config", true, "The notaql config file."); options.addOption("i", "inengine", true, "Execute for certain input engines"); options.addOption("o", "outengine", true, "Execute for certain output engines"); options.addOption("t", "test", true, "Execute certain test case only"); final CommandLineParser parser = new PosixParser(); final CommandLine cmd = parser.parse(options, args); if (cmd.hasOption("config")) { final String path = cmd.getOptionValue("config"); NotaQL.loadConfig(path); } inEngine = cmd.getOptionValue("inengine"); outEngine = cmd.getOptionValue("outengine"); testCase = cmd.getOptionValue("test"); runTests(); } public static void runTests() throws URISyntaxException, IOException { URI basePath = NotaQL.class.getResource(BASE_PATH).toURI(); Map<String, String> env = new HashMap<>(); env.put("create", "true"); FileSystem zipfs = FileSystems.newFileSystem(basePath, env); final List<Path> tests = Files.list(Paths.get(basePath)).filter(p -> p.toString().endsWith(".json")) .sorted((a, b) -> a.toString().compareTo(b.toString())).collect(Collectors.toList()); List<String> csv = new LinkedList<>(); for (Path test : tests) { if (testCase != null && !test.getFileName().toString().equals(testCase)) continue; final List<JSONObject> transformations = readArray(test); csv.add(test.getFileName().toString()); int i = 1; for (JSONObject transformation : transformations) { final String name = transformation.getString("name"); final String notaqlTransformation = composeTransformation(transformation); if (!(inEngine == null && outEngine == null || inEngine != null && transformation.getJSONObject("IN-ENGINE").getString("engine").equals(inEngine) || outEngine != null && transformation.getJSONObject("OUT-ENGINE").getString("engine") .equals(outEngine))) continue; System.out.println("Evaluation test (" + i++ + "/" + transformations.size() + "): " + test.getFileName() + ": " + name); List<Duration> durations = new LinkedList<>(); for (int j = 0; j < RUNS; j++) { clean(transformation); final Instant startTime = Instant.now(); NotaQL.evaluate(notaqlTransformation); final Instant endTime = Instant.now(); final Duration duration = Duration.between(startTime, endTime); durations.add(duration); System.out.println("Testrun(" + j + ") " + name + " took: " + duration); } System.out.println("!!=================================================================!!"); System.out.println("Test " + name + " took: " + durations.stream().map(Duration::toString).collect(Collectors.joining(", "))); System.out.println("Test " + name + " took millis: " + durations.stream() .map(d -> Long.toString(d.toMillis())).collect(Collectors.joining(", "))); System.out.println("Test " + name + " took on average (millis): " + durations.stream().mapToLong(Duration::toMillis).average()); System.out.println("Test " + name + " took on average (ignoring first - millis): " + durations.stream().skip(1).mapToLong(Duration::toMillis).average()); System.out.println("!!=================================================================!!"); csv.add(name); csv.add(durations.stream().map(d -> Long.toString(d.toMillis())).collect(Collectors.joining(","))); } } System.out.println(csv.stream().collect(Collectors.joining("\n"))); } private static void clean(JSONObject transformation) throws IOException { final JSONObject outEngine = transformation.getJSONObject("OUT-ENGINE"); final String engineName = outEngine.getString("engine"); if (engineName.equals("csv")) { deleteRecursive(Paths.get(outEngine.getString("csv_path"))); } if (engineName.equals("json")) { deleteRecursive(Paths.get(outEngine.getString("path"))); } } private static void deleteRecursive(Path path) throws IOException { if (!Files.exists(path)) return; Files.walk(path).sorted((a, b) -> b.compareTo(a)). // reverse; files before dirs forEach(p -> { try { Files.delete(p); } catch (IOException e) { /* ... */ } }); } private static String composeTransformation(JSONObject transformation) { final JSONObject inEngine = transformation.getJSONObject("IN-ENGINE"); final JSONObject outEngine = transformation.getJSONObject("OUT-ENGINE"); final String mapping = transformation.getString("transformation"); return "IN-ENGINE: " + composeEngine(inEngine) + ",\n" + "OUT-ENGINE: " + composeEngine(outEngine) + ",\n" + mapping; } private static String composeEngine(JSONObject engine) { final StringBuilder builder = new StringBuilder(); builder.append(engine.get("engine")); builder.append("("); final String params = StreamSupport .stream(Spliterators.spliteratorUnknownSize(engine.keys(), Spliterator.ORDERED), false) .filter(k -> !k.equals("engine")).map(k -> k + " <- " + toArg(k, engine)) .collect(Collectors.joining(", ")); builder.append(params); builder.append(")"); return builder.toString(); } private static String toArg(String key, JSONObject engine) { final Object val = engine.get(key); if (val instanceof Boolean || val instanceof Number) return val.toString(); return "'" + val.toString() + "'"; } private static List<JSONObject> readArray(Path path) throws IOException { final String input = Files.lines(path).collect(Collectors.joining()); final JSONArray jsonArray = new JSONArray(input); final List<JSONObject> elements = new LinkedList<>(); for (int i = 0; i < jsonArray.length(); i++) { final Object element = jsonArray.get(i); if (!(element instanceof JSONObject)) throw new IOException("Expecting an array of objects as input."); elements.add((JSONObject) element); } return elements; } }