ProfileData.java revision 2b3ee0ea07246b859a5b75d8a6102a7cce7ec838
13d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang/* 23d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * Copyright (C) 2012 The Android Open Source Project 33d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * 43d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License"); 53d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * you may not use this file except in compliance with the License. 63d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * You may obtain a copy of the License at 73d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * 83d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * http://www.apache.org/licenses/LICENSE-2.0 93d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * 103d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * Unless required by applicable law or agreed to in writing, software 113d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS, 123d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * See the License for the specific language governing permissions and 143d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * limitations under the License. 153d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang */ 163d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 173d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changpackage com.android.gallery3d.util; 183d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 193d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport android.util.Log; 203d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 212b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.common.Utils; 222b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 233d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport java.io.DataOutputStream; 243d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport java.io.FileOutputStream; 253d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport java.io.IOException; 263d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport java.util.ArrayList; 273d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport java.util.HashMap; 283d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport java.util.Map.Entry; 293d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 303d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// ProfileData keeps profiling samples in a tree structure. 313d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// The addSample() method adds a sample. The dumpToFile() method saves the data 323d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// to a file. The reset() method clears all samples. 333d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changpublic class ProfileData { 343d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private static final String TAG = "ProfileData"; 353d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 363d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private static class Node { 373d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public int id; // this is the name of this node, mapped from mNameToId 383d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public Node parent; 393d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public int sampleCount; 403d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public ArrayList<Node> children; 413d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public Node(Node parent, int id) { 423d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang this.parent = parent; 433d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang this.id = id; 443d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 453d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 463d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 473d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private Node mRoot; 483d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private int mNextId; 493d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private HashMap<String, Integer> mNameToId; 503d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private DataOutputStream mOut; 513d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private byte mScratch[] = new byte[4]; // scratch space for writeInt() 523d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 533d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public ProfileData() { 543d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mRoot = new Node(null, -1); // The id of the root node is unused. 553d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mNameToId = new HashMap<String, Integer>(); 563d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 573d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 583d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public void reset() { 593d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mRoot = new Node(null, -1); 603d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mNameToId.clear(); 613d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mNextId = 0; 623d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 633d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 643d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private int nameToId(String name) { 653d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Integer id = mNameToId.get(name); 663d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (id == null) { 673d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang id = ++mNextId; // The tool doesn't want id=0, so we start from 1. 683d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mNameToId.put(name, id); 693d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 703d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang return id; 713d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 723d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 733d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public void addSample(String[] stack) { 743d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang int[] ids = new int[stack.length]; 753d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang for (int i = 0; i < stack.length; i++) { 763d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang ids[i] = nameToId(stack[i]); 773d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 783d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 793d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Node node = mRoot; 803d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang for (int i = stack.length - 1; i >= 0; i--) { 813d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (node.children == null) { 823d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang node.children = new ArrayList<Node>(); 833d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 843d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 853d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang int id = ids[i]; 863d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang ArrayList<Node> children = node.children; 873d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang int j; 883d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang for (j = 0; j < children.size(); j++) { 893d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (children.get(j).id == id) break; 903d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 913d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (j == children.size()) { 923d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang children.add(new Node(node, id)); 933d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 943d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 953d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang node = children.get(j); 963d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 973d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 983d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang node.sampleCount++; 993d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1003d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1013d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public void dumpToFile(String filename) { 1023d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang try { 1033d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mOut = new DataOutputStream(new FileOutputStream(filename)); 1043d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // Start record 1053d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(0); 1063d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(3); 1073d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(1); 1083d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(20000); // Sampling period: 20ms 1093d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(0); 1103d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1113d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // Samples 1123d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeAllStacks(mRoot, 0); 1133d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1143d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // End record 1153d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(0); 1163d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(1); 1173d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(0); 1183d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeAllSymbols(); 1193d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } catch (IOException ex) { 1203d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Log.w("Failed to dump to file", ex); 1213d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } finally { 1223d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Utils.closeSilently(mOut); 1233d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1243d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1253d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1263d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // Writes out one stack, consisting of N+2 words: 1273d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // first word: sample count 1283d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // second word: depth of the stack (N) 1293d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // N words: each word is the id of one address in the stack 1303d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private void writeOneStack(Node node, int depth) throws IOException { 1313d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(node.sampleCount); 1323d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(depth); 1333d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang while (depth-- > 0) { 1343d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(node.id); 1353d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang node = node.parent; 1363d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1373d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1383d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1393d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private void writeAllStacks(Node node, int depth) throws IOException { 1403d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (node.sampleCount > 0) { 1413d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeOneStack(node, depth); 1423d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1433d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1443d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang ArrayList<Node> children = node.children; 1453d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (children != null) { 1463d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang for (int i = 0; i < children.size(); i++) { 1473d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeAllStacks(children.get(i), depth + 1); 1483d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1493d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1503d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1513d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1523d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // Writes out the symbol table. Each line is like: 1533d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // 0x17e java.util.ArrayList.isEmpty(ArrayList.java:319) 1543d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private void writeAllSymbols() throws IOException { 1553d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang for (Entry<String, Integer> entry : mNameToId.entrySet()) { 1563d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mOut.writeBytes(String.format("0x%x %s\n", entry.getValue(), entry.getKey())); 1573d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1583d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1593d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1603d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private void writeInt(int v) throws IOException { 1613d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mScratch[0] = (byte) v; 1623d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mScratch[1] = (byte) (v >> 8); 1633d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mScratch[2] = (byte) (v >> 16); 1643d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mScratch[3] = (byte) (v >> 24); 1653d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mOut.write(mScratch); 1663d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1673d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang} 168