/* * * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program 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 version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ import java.io.*; import java.util.*; /** * This program parses the event.log generated by the VM and * calculates the extend "pause" that can be noticed by the user. The * algorithm moves a "sliding window" across the execution history of * a program. If the amount of "stop-the-world" activities in a * sliding window exceeds the threshold, we discover a pause. * * For example, if window_size is 30 and pause_thresh is 10, and the * first 30 ms of the execution time contains 7 msec of GC and 5 msec * of compilation for a total of 12 ms of stop-the-world activities, * we declare that the first sliding window contains a pause. */ public class ParsePauses { /** * The size of the sliding window, in milliseconds. */ static int window_size = 30; /** * How much stop-the-world activities can happen in a sliding window * before we declare that the sliding window contains a pause. */ static int pause_thresh = 10; static boolean verbose = false; static class Node { double msec; boolean is_paused; String type; public String toString() { String s1 = new PrintfFormat("%10.3f").sprintf(msec); String s2 = new PrintfFormat("%-15s").sprintf(type); return s1 + (is_paused ? "**" : " ") + s2; } } public static void main(String args[]) throws Throwable { try { int n = 0; if (args[0].equals("-v")) { n++; verbose = true; } window_size = Integer.parseInt(args[n+0]); pause_thresh = Integer.parseInt(args[n+1]); } catch (Throwable t) {;} FileInputStream in = new FileInputStream("event.log"); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String s; Vector v = new Vector(); double last_msec = 0.0; int nestLevel = 0; while ((s = reader.readLine()) != null) { try { s = s.trim(); String num = s.substring(0, s.indexOf(' ')); double d = Double.parseDouble(num); Node n = new Node(); n.msec = d; if (s.endsWith("END")) { nestLevel --; } else { nestLevel ++; } n.is_paused = (nestLevel) > 0; n.type = s.substring(s.lastIndexOf(' ')).intern(); v.addElement(n); last_msec = d; } catch (Throwable t) {;} } int total_pauses = 0; int total_msecs = 0; int startIdx = 0; for (double msec = 0; msec < last_msec; msec += 1.0) { if ((startIdx = findStartIdx(v, startIdx, msec)) < 0) { break; } if (add_pauses(v, startIdx, msec)) { total_pauses ++; } total_msecs ++; } System.out.println("pauses = " + total_pauses + "/" + total_msecs); } // Find the last index that precedes msec static int findStartIdx(Vector v, int startIdx, double msec) { boolean found = false; for (int i=startIdx; i<v.size(); i++) { Node n = (Node)v.elementAt(i); if (n.msec > msec) { if (!found) { return startIdx; } else { break; } } if (n.msec <= msec) { startIdx = i; found = true; } } if (!found) { return -1; } else { return startIdx; } } static boolean add_pauses(Vector v, int startIdx, double begin) { double end = begin + window_size; for (int pass = 0; pass < 2; pass++) { Node lastNode = null; double total_paused = 0.0; if (pass == 1 && verbose) { System.out.println("========================================"); System.out.println("START" + begin); } for (int i=startIdx; i<v.size(); i++) { Node n = (Node)v.elementAt(i); if (pass == 1 && verbose) { System.out.print(" " + n); } if (lastNode != null && lastNode.is_paused) { double a = lastNode.msec; double b = n.msec; if (a < begin) { a = begin; } if (b > end) { b = end; } total_paused += (b - a); if (pass == 1 && verbose) { String s = new PrintfFormat("%7.3f").sprintf(b-a); System.out.print(" += " + s); } } if (pass == 1 && verbose) { System.out.println(); } lastNode = n; if (n.msec >= end) { break; } } if (total_paused > pause_thresh) { if (pass == 1) { String s = new PrintfFormat("%.3f").sprintf(total_paused); if (verbose) { System.out.println(); } System.out.println("Pause at " + begin + " ms" + " = " + s + " ms"); return true; } } else { return false; } } return true; } }