Analyze the program behavior every 20 minutes

I am working on a project in which I am trying to benchmark some of my client side code.

So for that I wrote a Multithreading program which will spawn multiple threads and each thread will run for particular duration of time and after the program is finished, I call logHistogramInfo() method in the finally block to print out the historgram information for me which will tell me how my client code has behaved.

Below is my code in which I am spawning multiple threads and in the finally block, I am calling the logHistogramInfo method-

public static void main(String[] args) {

    try {

        readPropertyFiles(args);

        //create thread pool with given size
        ExecutorService service = Executors.newFixedThreadPool(noOfThreads);

        long startTime = System.currentTimeMillis();
        long endTime = startTime + (durationOfRun * 60 * 1000);

        for (int i = 0; i < threads; i++) {
            service.submit(new CassandraReadTask(endTime, columnFamilyList));
        }

        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
    } catch (InterruptedException e) {

    } catch (Exception e) {

    } finally {
        logHistogramInfo();
    }

    LOG.info("All threads are finished");
}

Below is my histogram method-

private static void logHistogramInfo() {

    int[] definition = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 };
    long[] buckets = new long[definition.length];

    System.out.println("Milliseconds           Number");
    SortedSet<Long> keys = new TreeSet<Long>(CassandraTimer.histogram.keySet());
    for (long key : keys) {
        Long value = CassandraTimer.histogram.get(key);
        System.out.println(key + "                      " + value);
    }

    //Histogram information
    for (Long time : CassandraTimer.histogram.keySet()) {
        for (int i = definition.length - 1; i >= 0; i--) {
            if (time >= definition[i]) {
                buckets[i] += CassandraTimer.histogram.get(time);
                break;
            }
        }
    }
    for (int i = 0; i < definition.length; i++) {
        String period = "";
        if (i == definition.length - 1) {
            period = "greater than " + definition[i] + " ms";
        } else {
            period = "between " + (definition[i] + 1) + " and " + definition[i + 1] + " ms";
        }
        LOG.info(buckets[i] + " came back " + period);
    }
}

Problem Statement:-

Everthing is working fine for me. Now the only problem is, suppose If I am running my program for 10hours then I need to wait for my program to finish. And after 10 hours only, I can see what's the result is.

I am interested in seeing the result while the program is running. Just to get the idea how the program is behaving. I don't want to wait for 10 hours and then see the result.

Now I am thinking of, suppose I am running my program for 10 hours then after every 10 minutes or 20 minutes(it should be configurable) it should call logHistogramInfo() method and show me the result.

And after the program is finished, it will automatically call the logHistogramInfo() method in the finally block. So I will be able to get the full picture in the end. But after every 20 minutes, I can see how the program is behaving instead of waiting for the program to finish. Is this thing possible?

Any example will be of great help.

Updated code:-

With the below code, it is not printing the logs after every few minutes. I tried debugging and putting the breakpoint inside the try block and it is not hitting that breakpoint as well. Any idea why?

// queue some tasks
long startTime = System.currentTimeMillis();
long endTime = startTime + (durationOfRun * 60 * 1000);

for (int i = 0; i < threads; i++) {
        service.submit(new CassandraReadTask(endTime, columnFamilyList));
}

service.shutdown();

loggingAfterEveryXMinutes();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);


/**
 * This is a simple which will call the logHistogramInfo method after every X Minutes
 */
private static void loggingAfterEveryXMilliseconds() {
    new Thread() {
        public void run() {
            while (true) {
                try { 
                    Thread.sleep(loggingEveryXMilliseconds); 
                }
                catch (InterruptedException ex) {

                }
                logHistogramInfo();
            }
        }
    }.start();      
}

Answers


You have two choices here:

1) Pre-configure an "update period"

This is a solution you have already identified. It simply consists of setting up an additional thread, like so, to do the logging:

new Thread() {
    public void run() {
        while (true) {
            try { Thread.sleep(numMinutes * 60 * 1000); }
            catch (InterruptedException ex) { }
            logHistogramInfo();
        }
    }
};

2) Provide a hook where histogram info can be retrieved on demand

There are several ways to do this, but the most common one is to simply set up an HTTP server that you can hit from a browser to render the information (or, you can simply have the program render the histogram info to a log file whenever the HTTP server is hit)

Apache Commons is useful for quickly setting up this sort of thing, but there's really not a whole lot to it:

new Thread() {
    public void run() {
        ServerSocker serverSocket = new ServerSocket(12345);
        while (true) {
            Socket socket = serverSocket.accept();
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream());
            pw.println("Histogram Info");
            // Print histogram info
            pw.flush();  pw.close();
            socket.close();
        }
    }
}

Need Your Help

Grails: Load Data while Scrolling Page Down

javascript grails scroll

I want to dynamically load data while Scrolling a GSP Page Down like facebook does.

Make sure that randomly assigned attribute is not duplicating

javascript jquery html random

I have this scenario. There are six differently positioned placeholders on the page. I have six different words, and each word should be randomly assigned to one placeholder.