edu.mit.streamjit.tuner.RunApp.java Source code

Java tutorial

Introduction

Here is the source code for edu.mit.streamjit.tuner.RunApp.java

Source

/*
 * Copyright (c) 2013-2014 Massachusetts Institute of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package edu.mit.streamjit.tuner;

import static com.google.common.base.Preconditions.checkNotNull;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.google.common.base.Splitter;

import edu.mit.streamjit.api.StreamCompiler;
import edu.mit.streamjit.impl.common.Configuration;
import edu.mit.streamjit.impl.common.Configuration.IntParameter;
import edu.mit.streamjit.impl.common.Configuration.Parameter;
import edu.mit.streamjit.impl.common.Configuration.SwitchParameter;
import edu.mit.streamjit.impl.compiler2.Compiler2StreamCompiler;
import edu.mit.streamjit.impl.distributed.DistributedStreamCompiler;
import edu.mit.streamjit.test.Benchmark;
import edu.mit.streamjit.test.Benchmarker;
import edu.mit.streamjit.test.Datasets;
import edu.mit.streamjit.tuner.ConfigGenerator.sqliteAdapter;

/**
 * {@link RunApp} reads configuration, streamJit's app name and location
 * information from streamjit.db based on the passed arguments, runs the
 * streamJit app and update the database with the execution time. StreamJit's
 * opentuner Python script calls this to run the streamJit application.
 *
 * @author Sumanan sumanan@mit.edu
 * @since Sep 10, 2013
 *
 */
public class RunApp {

    /**
     * @param args
     *            args[0] - program name. args[1] - tune round.
     * @throws SQLException
     */
    public static void main(String[] args) throws SQLException {
        if (args.length < 2)
            throw new IllegalArgumentException("Not enough arguments to run the app");

        String benchmarkName = args[0];
        int round = Integer.parseInt(args[1]);

        System.out.println(String.format("JAVA Executing: %s Round - %d", benchmarkName, round));

        String dbPath = "streamjit.db";

        sqliteAdapter sqlite;
        try {
            sqlite = new sqliteAdapter();
        } catch (ClassNotFoundException e) {
            System.err.println("Sqlite3 database not found...couldn't update the database with the configutaion.");
            e.printStackTrace();
            return;
        }
        sqlite.connectDB(dbPath);

        ResultSet result = sqlite.executeQuery(String.format("SELECT * FROM apps WHERE name='%s'", benchmarkName));

        String confgString = result.getString("configuration");

        String sjDbPath = "sj" + benchmarkName + ".db";
        sqliteAdapter sjDb;
        try {
            sjDb = new sqliteAdapter();
        } catch (ClassNotFoundException e1) {
            // Actually this exception will not occur. If Sqlite3 did not
            // exists then it would have exit at previous return point.
            System.err.println("Sqlite3 database not found...couldn't update the database with the configutaion.");
            e1.printStackTrace();
            return;
        }
        sjDb.connectDB(sjDbPath);

        ResultSet result1 = sjDb.executeQuery(String.format("SELECT * FROM results WHERE Round=%d", round));

        String pyDict = result1.getString("SJConfig");

        Configuration config = Configuration.fromJson(getConfigurationString(confgString));

        Configuration cfg2 = rebuildConfiguration(pyDict, config);

        Benchmark app = Benchmarker.getBenchmarkByName(benchmarkName);
        StreamCompiler sc;
        IntParameter p = cfg2.getParameter("noOfMachines", IntParameter.class);
        if (p == null) {
            Compiler2StreamCompiler csc = new Compiler2StreamCompiler();
            csc.configuration(cfg2);
            sc = csc;
        } else {
            sc = new DistributedStreamCompiler(p.getValue(), cfg2);
        }

        double time = 0;
        try {
            Benchmarker.Result benchmarkResult = Benchmarker.runBenchmark(app, sc).get(0);
            if (benchmarkResult.isOK())
                time = benchmarkResult.runMillis();
            else if (benchmarkResult.kind() == Benchmarker.Result.Kind.TIMEOUT)
                time = -1;
            else if (benchmarkResult.kind() == Benchmarker.Result.Kind.EXCEPTION) {
                benchmarkResult.throwable().printStackTrace();
                time = -2;
            } else if (benchmarkResult.kind() == Benchmarker.Result.Kind.WRONG_OUTPUT) {
                System.out.println("WRONG OUTPUT");
                time = -2;
            }
        } catch (Exception e) {
            //The Benchmarker should catch everything, but just in case...
            e.printStackTrace();
            time = -2;
        } catch (OutOfMemoryError er) {
            MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
            System.out.println("******OutOfMemoryError******");
            MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
            int MEGABYTE = 1024 * 1024;
            long maxMemory = heapUsage.getMax() / MEGABYTE;
            long usedMemory = heapUsage.getUsed() / MEGABYTE;
            System.out.println("Memory Use :" + usedMemory + "M/" + maxMemory + "M");
            time = -3;
        }

        System.out.println(String.format("RunApp : Execution time - %f", time));

        String qry = String.format("UPDATE results SET Exectime=%f WHERE Round=%d", time, round);
        sjDb.executeUpdate(qry);
    }

    private static String getConfigurationString(String s) {
        String s1 = s.replaceAll("__class__", "ttttt");
        String s2 = s1.replaceAll("javaClassPath", "class");
        String s3 = s2.replaceAll("ttttt", "__class__");
        return s3;
    }

    /**
     * Creates a new {@link Configuration} from the received python dictionary
     * string. This is not a good way to do.
     * <p>
     * TODO: Need to add a method to {@link Configuration} so that the
     * configuration object can be updated from the python dict string. Now we
     * are destructing the old confg object and recreating a new one every time.
     * Not a appreciatable way.
     *
     * @param pythonDict
     *            Python dictionary string. Autotuner gives a dictionary of
     *            features with trial values.
     * @param config
     *            Old configuration object.
     * @return New configuration object with updated values from the pythonDict.
     */
    private static Configuration rebuildConfiguration(String pythonDict, Configuration config) {
        // System.out.println(pythonDict);
        checkNotNull(pythonDict, "Received Python dictionary is null");
        pythonDict = pythonDict.replaceAll("u'", "");
        pythonDict = pythonDict.replaceAll("':", "");
        pythonDict = pythonDict.replaceAll("\\{", "");
        pythonDict = pythonDict.replaceAll("\\}", "");
        Splitter dictSplitter = Splitter.on(", ").omitEmptyStrings().trimResults();
        Configuration.Builder builder = Configuration.builder();
        System.out.println("New parameter values from Opentuner...");
        for (String s : dictSplitter.split(pythonDict)) {
            String[] str = s.split(" ");
            if (str.length != 2)
                throw new AssertionError("Wrong python dictionary...");
            Parameter p = config.getParameter(str[0]);
            if (p == null)
                continue;
            if (p instanceof IntParameter) {
                IntParameter ip = (IntParameter) p;
                builder.addParameter(
                        new IntParameter(ip.getName(), ip.getMin(), ip.getMax(), Integer.parseInt(str[1])));

            } else if (p instanceof SwitchParameter<?>) {
                SwitchParameter sp = (SwitchParameter) p;
                Class<?> type = sp.getGenericParameter();
                int val = Integer.parseInt(str[1]);
                SwitchParameter<?> sp1 = new SwitchParameter(sp.getName(), type, sp.getUniverse().get(val),
                        sp.getUniverse());
                builder.addParameter(sp1);
            }
        }
        return builder.build();
    }
}