1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dalvik.system.profiler;
18 
19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.io.PrintWriter;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Comparator;
25 import java.util.Date;
26 import java.util.List;
27 
28 /**
29  * AsciiHprofWriter produces hprof compatible text output for use with
30  * third party tools such as PerfAnal.
31  */
32 public final class AsciiHprofWriter {
33 
34     private final HprofData data;
35     private final PrintWriter out;
36 
37     /**
38      * Writes the provided data to the specified stream.
39      */
write(HprofData data, OutputStream outputStream)40     public static void write(HprofData data, OutputStream outputStream) throws IOException {
41         new AsciiHprofWriter(data, outputStream).write();
42     }
43 
AsciiHprofWriter(HprofData data, OutputStream outputStream)44     private AsciiHprofWriter(HprofData data, OutputStream outputStream) {
45         this.data = data;
46         this.out = new PrintWriter(outputStream);
47     }
48 
write()49     private void write() throws IOException {
50         for (HprofData.ThreadEvent e : data.getThreadHistory()) {
51             out.println(e);
52         }
53 
54         List<HprofData.Sample> samples
55                 = new ArrayList<HprofData.Sample>(data.getSamples());
56         Collections.sort(samples, SAMPLE_COMPARATOR);
57         int total = 0;
58         for (HprofData.Sample sample : samples) {
59             HprofData.StackTrace stackTrace = sample.stackTrace;
60             int count = sample.count;
61             total += count;
62             out.printf("TRACE %d: (thread=%d)\n",
63                        stackTrace.stackTraceId,
64                        stackTrace.threadId);
65             for (StackTraceElement e : stackTrace.stackFrames) {
66                 out.printf("\t%s\n", e);
67             }
68         }
69         Date now = new Date(data.getStartMillis());
70         // "CPU SAMPLES BEGIN (total = 826) Wed Jul 21 12:03:46 2010"
71         out.printf("CPU SAMPLES BEGIN (total = %d) %ta %tb %td %tT %tY\n",
72                    total, now, now, now, now, now);
73         out.printf("rank   self  accum   count trace method\n");
74         int rank = 0;
75         double accum = 0;
76         for (HprofData.Sample sample : samples) {
77             rank++;
78             HprofData.StackTrace stackTrace = sample.stackTrace;
79             int count = sample.count;
80             double self = (double)count/(double)total;
81             accum += self;
82 
83             // "   1 65.62% 65.62%     542 300302 java.lang.Long.parseLong"
84             out.printf("% 4d% 6.2f%%% 6.2f%% % 7d % 5d %s.%s\n",
85                        rank, self*100, accum*100, count, stackTrace.stackTraceId,
86                        stackTrace.stackFrames[0].getClassName(),
87                        stackTrace.stackFrames[0].getMethodName());
88         }
89         out.printf("CPU SAMPLES END\n");
90         out.flush();
91     }
92 
93     private static final Comparator<HprofData.Sample> SAMPLE_COMPARATOR
94             = new Comparator<HprofData.Sample>() {
95         public int compare(HprofData.Sample s1, HprofData.Sample s2) {
96             return s2.count - s1.count;
97         }
98     };
99 }
100