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
17package dalvik.system.profiler;
18
19import java.io.IOException;
20import java.io.OutputStream;
21import java.io.PrintWriter;
22import java.util.ArrayList;
23import java.util.Collections;
24import java.util.Comparator;
25import java.util.Date;
26import java.util.List;
27
28/**
29 * AsciiHprofWriter produces hprof compatible text output for use with
30 * third party tools such as PerfAnal.
31 */
32public 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     */
40    public static void write(HprofData data, OutputStream outputStream) throws IOException {
41        new AsciiHprofWriter(data, outputStream).write();
42    }
43
44    private AsciiHprofWriter(HprofData data, OutputStream outputStream) {
45        this.data = data;
46        this.out = new PrintWriter(outputStream);
47    }
48
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