001: /*
002: * Janino - An embedded Java[TM] compiler
003: *
004: * Copyright (c) 2006, Arno Unkrig
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * 2. Redistributions in binary form must reproduce the above
014: * copyright notice, this list of conditions and the following
015: * disclaimer in the documentation and/or other materials
016: * provided with the distribution.
017: * 3. The name of the author may not be used to endorse or promote
018: * products derived from this software without specific prior
019: * written permission.
020: *
021: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
022: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
023: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
024: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
025: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
026: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
027: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
028: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
029: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
030: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
031: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
032: */
033:
034: package org.codehaus.janino.tools;
035:
036: import java.io.*;
037: import java.text.*;
038: import java.util.*;
039:
040: /**
041: * Example for object allocation statistics:
042: *
043: * java -Xrunhprof:heap=sites,monitor=n,cutoff=0,depth=4 MyClass
044: */
045: public class HprofScrubber {
046: private static class Site {
047: public final int allocatedBytes;
048: public final int allocatedObjects;
049: public final int traceNumber;
050: public final String className;
051:
052: public Site(int allocatedBytes, int allocatedObjects,
053: int traceNumber, String className) {
054: this .allocatedBytes = allocatedBytes;
055: this .allocatedObjects = allocatedObjects;
056: this .traceNumber = traceNumber;
057: this .className = className;
058: }
059: }
060:
061: private static class Sample {
062: public final int count;
063: public final int traceNumber;
064:
065: public Sample(int count, int traceNumber) {
066: this .count = count;
067: this .traceNumber = traceNumber;
068: }
069: }
070:
071: public static void main(String[] args) throws Exception {
072: String fileName = args.length == 0 ? "java.hprof.txt" : args[0];
073:
074: BufferedReader br = new BufferedReader(new FileReader(fileName));
075: try {
076: Map traces = new HashMap(); // Integer number => String[] stackFrames
077: List sites = new ArrayList(); // Site
078: List samples = new ArrayList(); // Sample
079:
080: String s = br.readLine();
081: while (s != null) {
082: if (s.startsWith("SITES BEGIN")) {
083: br.readLine();
084: br.readLine();
085: for (;;) {
086: s = br.readLine();
087: if (s.startsWith("SITES END"))
088: break;
089: StringTokenizer st = new StringTokenizer(s);
090: st.nextToken(); // rank
091: st.nextToken(); // percent self
092: st.nextToken(); // percent accum
093: st.nextToken(); // live bytes
094: st.nextToken(); // live objects
095: sites.add(new Site(Integer.parseInt(st
096: .nextToken()), // allocatedBytes
097: Integer.parseInt(st.nextToken()), // allocatedObjects
098: Integer.parseInt(st.nextToken()), // traceNumber
099: st.nextToken() // className
100: ));
101: }
102: } else if (s.startsWith("TRACE ") && s.endsWith(":")) {
103: int traceNumber = Integer.parseInt(s.substring(6, s
104: .length() - 1));
105: List l = new ArrayList();
106: for (;;) {
107: s = br.readLine();
108: if (!s.startsWith("\t"))
109: break;
110: l.add(s.substring(1));
111: }
112: traces.put(new Integer(traceNumber), l
113: .toArray(new String[l.size()]));
114: } else if (s.startsWith("CPU SAMPLES BEGIN")) {
115: br.readLine();
116: for (;;) {
117: s = br.readLine();
118: if (s.startsWith("CPU SAMPLES END"))
119: break;
120: StringTokenizer st = new StringTokenizer(s);
121: st.nextToken(); // rank
122: st.nextToken(); // percent self
123: st.nextToken(); // percent accum
124: int count = Integer.parseInt(st.nextToken());
125: if (count == 0)
126: continue;
127: int trace = Integer.parseInt(st.nextToken());
128: samples.add(new Sample(count, trace));
129: }
130: } else {
131: s = br.readLine();
132: }
133: }
134:
135: HprofScrubber.dumpSites((Site[]) sites
136: .toArray(new Site[sites.size()]), traces);
137:
138: HprofScrubber.dumpSamples((Sample[]) samples
139: .toArray(new Sample[samples.size()]), traces);
140:
141: } finally {
142: try {
143: br.close();
144: } catch (IOException e) {
145: }
146: }
147: }
148:
149: private static void dumpSites(Site[] ss, Map traces) {
150: Arrays.sort(ss, new Comparator() {
151: public int compare(Object o1, Object o2) {
152: return ((Site) o2).allocatedBytes
153: - ((Site) o1).allocatedBytes;
154: }
155: });
156:
157: int totalAllocatedBytes = 0, totalAllocatedObjects = 0;
158: for (int i = 0; i < ss.length; ++i) {
159: Site site = ss[i];
160: totalAllocatedBytes += site.allocatedBytes;
161: totalAllocatedObjects += site.allocatedObjects;
162: }
163:
164: System.out.println(" percent alloc'ed");
165: System.out
166: .println("rank self accum bytes objects class name");
167: System.out.println("Total: " + totalAllocatedBytes
168: + " " + totalAllocatedObjects);
169:
170: double accumulatedPercentage = 0.0;
171: MessageFormat mf = new MessageFormat(
172: "{0,number,00000} {1,number,00.00}% {2,number,00.00}% {3,number,000000000} {4,number,000000000} {5}");
173: for (int i = 0; i < ss.length; ++i) {
174: Site site = ss[i];
175: double selfPercentage = 100.0 * ((double) site.allocatedBytes / (double) totalAllocatedBytes);
176: accumulatedPercentage += selfPercentage;
177: // System.out.println((i + 1) + " " + selfPercentage + "% " + accumulatedPercentage + "% " + site.allocatedBytes + " " + site.allocatedObjects + " " + site.className);
178: System.out.println(mf.format(
179: new Object[] { new Integer(i + 1),
180: new Double(selfPercentage),
181: new Double(accumulatedPercentage),
182: new Integer(site.allocatedBytes),
183: new Integer(site.allocatedObjects),
184: site.className }, new StringBuffer(),
185: new FieldPosition(0)));
186: String[] stackFrames = (String[]) traces.get(new Integer(
187: site.traceNumber));
188: if (stackFrames != null) {
189: for (int j = 0; j < stackFrames.length; ++j) {
190: System.out.println(" "
191: + stackFrames[j]);
192: }
193: }
194: }
195: }
196:
197: private static void dumpSamples(Sample[] ss, Map traces) {
198: int totalCount = 0;
199: for (int i = 0; i < ss.length; ++i)
200: totalCount += ss[i].count;
201:
202: System.out.println(" percent");
203: System.out.println("rank self accum count");
204: System.out.println("Total: " + totalCount);
205:
206: double accumulatedPercentage = 0.0;
207: MessageFormat mf = new MessageFormat(
208: "{0,number,00000} {1,number,00.00}% {2,number,00.00}% {3,number,000000000}");
209: for (int i = 0; i < ss.length; ++i) {
210: Sample sample = ss[i];
211: double selfPercentage = 100.0 * ((double) sample.count / (double) totalCount);
212: accumulatedPercentage += selfPercentage;
213: // System.out.println((i + 1) + " " + selfPercentage + "% " + accumulatedPercentage + "% " + site.allocatedBytes + " " + site.allocatedObjects + " " + site.className);
214: System.out.println(mf.format(new Object[] {
215: new Integer(i + 1), new Double(selfPercentage),
216: new Double(accumulatedPercentage),
217: new Integer(sample.count) }, new StringBuffer(),
218: new FieldPosition(0)));
219: String[] stackFrames = (String[]) traces.get(new Integer(
220: sample.traceNumber));
221: if (stackFrames != null) {
222: for (int j = 0; j < stackFrames.length; ++j) {
223: System.out.println(" "
224: + stackFrames[j]);
225: }
226: }
227: }
228: }
229: }
|