165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/*
265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2010 The Android Open Source Project
365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License");
565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License.
665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at
765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *      http://www.apache.org/licenses/LICENSE-2.0
965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software
1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS,
1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and
1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License.
1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpackage dalvik.system.profiler;
1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.IOException;
2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.OutputStream;
2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.PrintWriter;
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.ArrayList;
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.Collections;
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.Comparator;
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.Date;
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.List;
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/**
2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * AsciiHprofWriter produces hprof compatible text output for use with
3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * third party tools such as PerfAnal.
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic final class AsciiHprofWriter {
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private final HprofData data;
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private final PrintWriter out;
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /**
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * Writes the provided data to the specified stream.
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public static void write(HprofData data, OutputStream outputStream) throws IOException {
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        new AsciiHprofWriter(data, outputStream).write();
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private AsciiHprofWriter(HprofData data, OutputStream outputStream) {
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        this.data = data;
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        this.out = new PrintWriter(outputStream);
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private void write() throws IOException {
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        for (HprofData.ThreadEvent e : data.getThreadHistory()) {
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            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