gsn.tests.performance.Queries.java Source code

Java tutorial

Introduction

Here is the source code for gsn.tests.performance.Queries.java

Source

/**
* Global Sensor Networks (GSN) Source Code
* Copyright (c) 2006-2014, Ecole Polytechnique Federale de Lausanne (EPFL)
* 
* This file is part of GSN.
* 
* GSN is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 
* GSN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with GSN.  If not, see <http://www.gnu.org/licenses/>.
* 
* File: src/gsn/tests/performance/Queries.java
*
* @author Timotee Maret
*
*/

package gsn.tests.performance;

import gsn.beans.DataField;
import org.apache.commons.math.stat.descriptive.SummaryStatistics;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParserFactory;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

public class Queries {

    /**
     * Nb of queries per Thread.
     */
    private int nbQueries;

    /**
     * Max Nb of Threads executing the queries.
     */
    private int nbThreads;

    /**
     * Max Nb of Element per query
     */
    private int maxQuerySize = -1;

    /**
     * URL of the GSN instance being evaluated.
     */
    private String gsnUrl = "http://localhost:22001";

    private HashMap<String, ArrayList<DataField>> mapping;

    private ExecutorService executor;

    private SAXParserFactory saxParserFactory;

    public Queries(int nbQueries, int nbThreads) {
        this.nbQueries = nbQueries;
        this.nbThreads = nbThreads;
        executor = Executors.newFixedThreadPool(nbThreads);
        saxParserFactory = SAXParserFactory.newInstance();
        mapping = new HashMap<String, ArrayList<DataField>>();
    }

    public Queries setMaxQuerySize(int maxQuerySize) {
        this.maxQuerySize = maxQuerySize;
        return this;
    }

    public Queries setGsnUrl(String gsnUrl) {
        this.gsnUrl = gsnUrl;
        return this;
    }

    private void runQueries() {

        ArrayList<Future<QueryResult>> futures = new ArrayList<Future<QueryResult>>();

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < nbQueries; i++) {
            // Pick the next vs
            //int index = (int) (Math.random() * mapping.size());
            int index = i;
            Map.Entry<String, ArrayList<DataField>> entry = (Map.Entry<String, ArrayList<DataField>>) mapping
                    .entrySet().toArray()[index];
            String vsName = entry.getKey();
            int nbFields = entry.getValue().size();
            // Build the query
            StringBuilder query = new StringBuilder(gsnUrl).append("/multidata?vs[0]=").append(vsName)
                    .append("&field[0]=All").append("&download_mode=inline").append("&download_format=csv")
                    .append("&nb=SPECIFIED&nb_value=").append(maxQuerySize);
            // TODO Extend with Conditions, aggregations.
            futures.add(executor.submit(new QueryTask(query.toString(), nbFields, vsName)));
        }

        // Go through the results and compute the stats
        SummaryStatistics execTime = new SummaryStatistics();
        SummaryStatistics tuples = new SummaryStatistics();
        SummaryStatistics fields = new SummaryStatistics();
        SummaryStatistics datas = new SummaryStatistics();
        SummaryStatistics tuplesRate = new SummaryStatistics();
        SummaryStatistics fieldsRate = new SummaryStatistics();
        SummaryStatistics datasRate = new SummaryStatistics();

        //int rowsSum = 0;
        //int fieldsSum = 0;
        //int dataSizeSum = 0;
        for (Future<QueryResult> result : futures) {
            try {
                QueryResult r = result.get();
                double deltaInSec = r.delta / 1000.0d;
                double dataInMeg = r.dataSize * 8.0d / (1024.0d * 1024.0d);
                System.out.println(r);
                execTime.addValue(deltaInSec); // s
                tuples.addValue(r.rows);
                fields.addValue(r.nbFields);
                datas.addValue(dataInMeg); // MB
                //
                tuplesRate.addValue(r.rows / deltaInSec); // tuple/s
                fieldsRate.addValue(r.nbFields / deltaInSec); // field/s
                datasRate.addValue(dataInMeg / deltaInSec); //MB/s
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
        long endTime = System.currentTimeMillis();
        //

        //
        float evalDuration = (endTime - startTime) / 1000.0f; // s
        System.out.println(new StringBuilder().append("\n------ GSN Queries Result --------").append("\n")
                .append("| URL: ").append(gsnUrl).append("\n").append("| Eval duration: ")
                .append(format(evalDuration)).append(" [s]\n").append("| Nb Queries   : ").append(nbQueries)
                .append("\n").append("| Tuples       : ").append(printStats(tuples, "no unit")).append("\n")
                .append("| Fields       : ").append(printStats(fields, "no unit")).append("\n")
                .append("| Raw Data     : ").append(printStats(datas, "MB")).append("\n")
                .append("| Download time: ").append(printStats(execTime, "s")).append("\n")
                .append("| Tuple Rate   : ").append(printStats(tuplesRate, "tuple/s")).append("\n")
                .append("| Field Rate   : ").append(printStats(fieldsRate, "field/s")).append("\n")
                .append("| Data Rate    : ").append(printStats(datasRate, "MB/s")).append("\n")
                .append("-----------------------------------\n"));

        executor.shutdown();
    }

    private String printStats(SummaryStatistics stats, String unit) {
        return new StringBuilder().append("sum:").append(format(stats.getSum())).append(", min:")
                .append(format(stats.getMin())).append(", max:").append(format(stats.getMax())).append(", mean:")
                .append(format(stats.getMean())).append(", var:").append(format(stats.getVariance())).append(" [")
                .append(unit).append("]").toString();
    }

    private String format(Number value) {
        return new DecimalFormat("###.000").format(value);
    }

    private class QueryTask implements Callable<QueryResult> {
        private String query;
        private int nbFields;
        private String vsName;

        public QueryTask(String query, int nbFields, String vsName) {
            this.query = query;
            this.nbFields = nbFields;
            this.vsName = vsName;
        }

        public QueryResult call() {
            int rows = 0;
            int dataSize = 0;
            long startTime = System.currentTimeMillis();
            //
            HttpGet getOp = new HttpGet(query);
            HttpResponse response = null;
            try {
                response = new DefaultHttpClient().execute(getOp);
                int status = response.getStatusLine().getStatusCode();
                if (status == HttpURLConnection.HTTP_OK) {

                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(response.getEntity().getContent()));
                    String line = null;
                    while ((line = br.readLine()) != null) {
                        if (!line.startsWith("#")) {
                            rows++;
                            dataSize += line.length();
                        }
                    }
                } else
                    System.out.println("Failed to get the data for query: " + query + ", status: " + status);
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
            //
            long stopTime = System.currentTimeMillis();
            long delta = stopTime - startTime;

            QueryResult rq = new QueryResult(delta, rows, dataSize, nbFields, vsName);

            return rq;
        }
    }

    private class QueryResult {
        private long delta;
        private int rows;
        private int dataSize;
        private int nbFields;
        private String vsName;

        public QueryResult(long delta, int rows, int dataSize, int nbFields, String vsName) {
            this.delta = delta;
            this.rows = rows;
            this.dataSize = dataSize;
            this.nbFields = nbFields;
            this.vsName = vsName;
        }

        public String toString() {
            return new StringBuilder().append("vsname: ").append(vsName).append(", time: ")
                    .append(Long.toString(delta)).append(", rows: ").append(rows).append(", data: ")
                    .append(dataSize).append(", nbFields: ").append(nbFields).append(", nbItems: ")
                    .append(rows * nbFields).append(", items/s: ")
                    .append((double) (rows * nbFields * 1000.0) / delta)
                    //.append(", query: ")
                    //.append(query)
                    .toString();
        }
    }

    public static void main(String[] args) {
        Queries queries = new Queries(Integer.parseInt(System.getProperty("nbQueries")),
                Integer.parseInt(System.getProperty("nbThreads")));
        //
        String op; // optional parameter
        if ((op = System.getProperty("maxQuerySize")) != null)
            queries.setMaxQuerySize(Integer.parseInt(op));
        if ((op = System.getProperty("gsnUrl")) != null)
            queries.setGsnUrl(op);
        //
        queries.updateListOfVirtualSensors();
        //
        queries.runQueries();

    }

    private void updateListOfVirtualSensors() {
        HttpGet getOp = new HttpGet(gsnUrl + "/gsn");
        HttpResponse response = null;
        try {
            response = new DefaultHttpClient().execute(getOp);
            int status = response.getStatusLine().getStatusCode();
            if (status == HttpURLConnection.HTTP_OK) {
                saxParserFactory.newSAXParser().parse(response.getEntity().getContent(),
                        new ContainerInfoHandler(mapping));
            } else
                System.out.println(
                        "Failed to get the list of virtual sensors from: " + gsnUrl + ", status: " + status);
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }

    private class ContainerInfoHandler extends DefaultHandler {
        HashMap<String, ArrayList<DataField>> mapping;
        String vsName;
        ArrayList<DataField> fields;

        public ContainerInfoHandler(HashMap<String, ArrayList<DataField>> mapping) {
            this.mapping = mapping;
        }

        public void startElement(String uri, String localName, String qName, Attributes attributes) {
            if ("virtual-sensor".equalsIgnoreCase(qName)) {
                vsName = attributes.getValue("name");
                fields = new ArrayList<DataField>();
            } else if ("field".equalsIgnoreCase(qName)) {
                if (attributes.getValue("name") != null && attributes.getValue("type") != null) {
                    fields.add(new DataField(attributes.getValue("name"), attributes.getValue("type")));
                }
            }
        }

        public void endElement(String uri, String localName, String qName) throws SAXException {
            if ("virtual-sensor".equalsIgnoreCase(qName)) {
                mapping.put(vsName, fields);
            }
        }
    }
}