ProfileData.java revision 7817979db0c52ffeacb951625b1e821eba303285
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 { 347817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @SuppressWarnings("unused") 353d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private static final String TAG = "ProfileData"; 363d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 373d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private static class Node { 383d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public int id; // this is the name of this node, mapped from mNameToId 393d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public Node parent; 403d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public int sampleCount; 413d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public ArrayList<Node> children; 423d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public Node(Node parent, int id) { 433d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang this.parent = parent; 443d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang this.id = id; 453d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 463d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 473d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 483d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private Node mRoot; 493d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private int mNextId; 503d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private HashMap<String, Integer> mNameToId; 513d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private DataOutputStream mOut; 523d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private byte mScratch[] = new byte[4]; // scratch space for writeInt() 533d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 543d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public ProfileData() { 553d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mRoot = new Node(null, -1); // The id of the root node is unused. 563d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mNameToId = new HashMap<String, Integer>(); 573d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 583d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 593d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public void reset() { 603d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mRoot = new Node(null, -1); 613d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mNameToId.clear(); 623d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mNextId = 0; 633d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 643d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 653d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private int nameToId(String name) { 663d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Integer id = mNameToId.get(name); 673d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (id == null) { 683d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang id = ++mNextId; // The tool doesn't want id=0, so we start from 1. 693d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mNameToId.put(name, id); 703d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 713d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang return id; 723d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 733d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 743d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public void addSample(String[] stack) { 753d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang int[] ids = new int[stack.length]; 763d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang for (int i = 0; i < stack.length; i++) { 773d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang ids[i] = nameToId(stack[i]); 783d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 793d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 803d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Node node = mRoot; 813d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang for (int i = stack.length - 1; i >= 0; i--) { 823d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (node.children == null) { 833d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang node.children = new ArrayList<Node>(); 843d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 853d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 863d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang int id = ids[i]; 873d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang ArrayList<Node> children = node.children; 883d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang int j; 893d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang for (j = 0; j < children.size(); j++) { 903d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (children.get(j).id == id) break; 913d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 923d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (j == children.size()) { 933d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang children.add(new Node(node, id)); 943d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 953d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 963d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang node = children.get(j); 973d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 983d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 993d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang node.sampleCount++; 1003d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1013d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1023d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public void dumpToFile(String filename) { 1033d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang try { 1043d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mOut = new DataOutputStream(new FileOutputStream(filename)); 1053d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // Start record 1063d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(0); 1073d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(3); 1083d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(1); 1093d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(20000); // Sampling period: 20ms 1103d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(0); 1113d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1123d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // Samples 1133d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeAllStacks(mRoot, 0); 1143d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1153d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // End record 1163d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(0); 1173d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(1); 1183d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(0); 1193d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeAllSymbols(); 1203d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } catch (IOException ex) { 1213d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Log.w("Failed to dump to file", ex); 1223d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } finally { 1233d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Utils.closeSilently(mOut); 1243d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1253d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1263d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1273d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // Writes out one stack, consisting of N+2 words: 1283d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // first word: sample count 1293d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // second word: depth of the stack (N) 1303d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // N words: each word is the id of one address in the stack 1313d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private void writeOneStack(Node node, int depth) throws IOException { 1323d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(node.sampleCount); 1333d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(depth); 1343d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang while (depth-- > 0) { 1353d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeInt(node.id); 1363d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang node = node.parent; 1373d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1383d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1393d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1403d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private void writeAllStacks(Node node, int depth) throws IOException { 1413d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (node.sampleCount > 0) { 1423d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeOneStack(node, depth); 1433d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1443d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1453d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang ArrayList<Node> children = node.children; 1463d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (children != null) { 1473d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang for (int i = 0; i < children.size(); i++) { 1483d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang writeAllStacks(children.get(i), depth + 1); 1493d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1503d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1513d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1523d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1533d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // Writes out the symbol table. Each line is like: 1543d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang // 0x17e java.util.ArrayList.isEmpty(ArrayList.java:319) 1553d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private void writeAllSymbols() throws IOException { 1563d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang for (Entry<String, Integer> entry : mNameToId.entrySet()) { 1573d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mOut.writeBytes(String.format("0x%x %s\n", entry.getValue(), entry.getKey())); 1583d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1593d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1603d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 1613d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private void writeInt(int v) throws IOException { 1623d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mScratch[0] = (byte) v; 1633d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mScratch[1] = (byte) (v >> 8); 1643d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mScratch[2] = (byte) (v >> 16); 1653d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mScratch[3] = (byte) (v >> 24); 1663d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mOut.write(mScratch); 1673d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 1683d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang} 169