1b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler/* 2b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Copyright (C) 2015 The Android Open Source Project 3b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * 4b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Licensed under the Apache License, Version 2.0 (the "License"); 5b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * you may not use this file except in compliance with the License. 6b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * You may obtain a copy of the License at 7b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * 8b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * http://www.apache.org/licenses/LICENSE-2.0 9b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * 10b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Unless required by applicable law or agreed to in writing, software 11b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * distributed under the License is distributed on an "AS IS" BASIS, 12b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * See the License for the specific language governing permissions and 14b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * limitations under the License. 15b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */ 16b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 17b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerpackage com.android.ahat; 18b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 19b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport com.android.tools.perflib.heap.ClassObj; 20b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport com.android.tools.perflib.heap.Heap; 21b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport com.android.tools.perflib.heap.Instance; 22b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport com.android.tools.perflib.heap.StackFrame; 23b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.util.ArrayList; 24b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.util.Collection; 25b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.util.HashMap; 26b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.util.Iterator; 27b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.util.List; 28b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.util.Map; 29b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 30b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerclass Site { 31b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // The site that this site was directly called from. 32b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // mParent is null for the root site. 33b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler private Site mParent; 34b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 35b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // A description of the Site. Currently this is used to uniquely identify a 36b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // site within its parent. 37b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler private String mName; 38b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 39b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // To identify this site, we pick one stack trace where we have seen the 40b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // site. mStackId is the id for that stack trace, and mStackDepth is the 41b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // depth of this site in that stack trace. 42b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // For the root site, mStackId is 0 and mStackDepth is 0. 43b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler private int mStackId; 44b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler private int mStackDepth; 45b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 46b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Mapping from heap name to the total size of objects allocated in this 47b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // site (including child sites) on the given heap. 48b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler private Map<String, Long> mSizesByHeap; 49b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 50b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Mapping from child site name to child site. 51b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler private Map<String, Site> mChildren; 52b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 53b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // List of all objects allocated in this site (including child sites). 54b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler private List<Instance> mObjects; 55b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler private List<ObjectsInfo> mObjectsInfos; 56b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler private Map<Heap, Map<ClassObj, ObjectsInfo>> mObjectsInfoMap; 57b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 58b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public static class ObjectsInfo { 59b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public Heap heap; 60b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public ClassObj classObj; 61b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public long numInstances; 62b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public long numBytes; 63b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 64b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public ObjectsInfo(Heap heap, ClassObj classObj, long numInstances, long numBytes) { 65b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler this.heap = heap; 66b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler this.classObj = classObj; 67b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler this.numInstances = numInstances; 68b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler this.numBytes = numBytes; 69b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 70b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 71b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 72b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler /** 73b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Construct a root site. 74b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */ 75b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public Site(String name) { 76b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler this(null, name, 0, 0); 77b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 78b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 79b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public Site(Site parent, String name, int stackId, int stackDepth) { 80b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mParent = parent; 81b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mName = name; 82b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mStackId = stackId; 83b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mStackDepth = stackDepth; 84b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mSizesByHeap = new HashMap<String, Long>(); 85b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mChildren = new HashMap<String, Site>(); 86b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mObjects = new ArrayList<Instance>(); 87b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mObjectsInfos = new ArrayList<ObjectsInfo>(); 88b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mObjectsInfoMap = new HashMap<Heap, Map<ClassObj, ObjectsInfo>>(); 89b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 90b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 91b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler /** 92b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Add an instance to this site. 93b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Returns the site at which the instance was allocated. 94b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */ 95b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public Site add(int stackId, int stackDepth, Iterator<StackFrame> path, Instance inst) { 96b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mObjects.add(inst); 97b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 98b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler String heap = inst.getHeap().getName(); 99b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mSizesByHeap.put(heap, getSize(heap) + inst.getSize()); 100b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 101b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler Map<ClassObj, ObjectsInfo> classToObjectsInfo = mObjectsInfoMap.get(inst.getHeap()); 102b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (classToObjectsInfo == null) { 103b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler classToObjectsInfo = new HashMap<ClassObj, ObjectsInfo>(); 104b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mObjectsInfoMap.put(inst.getHeap(), classToObjectsInfo); 105b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 106b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 107b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler ObjectsInfo info = classToObjectsInfo.get(inst.getClassObj()); 108b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (info == null) { 109b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler info = new ObjectsInfo(inst.getHeap(), inst.getClassObj(), 0, 0); 110b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mObjectsInfos.add(info); 111b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler classToObjectsInfo.put(inst.getClassObj(), info); 112b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 113b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 114b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler info.numInstances++; 115b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler info.numBytes += inst.getSize(); 116b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 117b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (path.hasNext()) { 118b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler String next = path.next().toString(); 119b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler Site child = mChildren.get(next); 120b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (child == null) { 121b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler child = new Site(this, next, stackId, stackDepth + 1); 122b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler mChildren.put(next, child); 123b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 124b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return child.add(stackId, stackDepth + 1, path, inst); 125b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } else { 126b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return this; 127b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 128b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 129b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 130b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Get the size of a site for a specific heap. 131b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public long getSize(String heap) { 132b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler Long val = mSizesByHeap.get(heap); 133b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (val == null) { 134b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return 0; 135b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 136b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return val; 137b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 138b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 139b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler /** 140b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Get the list of objects allocated under this site. Includes objects 141b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * allocated in children sites. 142b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */ 143b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public Collection<Instance> getObjects() { 144b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return mObjects; 145b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 146b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 147b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public List<ObjectsInfo> getObjectsInfos() { 148b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return mObjectsInfos; 149b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 150b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 151b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Get the combined size of the site for all heaps. 152b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public long getTotalSize() { 153b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler long size = 0; 154b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler for (Long val : mSizesByHeap.values()) { 155b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler size += val; 156b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 157b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return size; 158b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 159b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 160b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler /** 161b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Return the site this site was called from. 162b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Returns null for the root site. 163b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */ 164b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public Site getParent() { 165b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return mParent; 166b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 167b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 168b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public String getName() { 169b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return mName; 170b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 171b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 172b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Returns the hprof id of a stack this site appears on. 173b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public int getStackId() { 174b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return mStackId; 175b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 176b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 177b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Returns the stack depth of this site in the stack whose id is returned 178b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // by getStackId(). 179b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public int getStackDepth() { 180b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return mStackDepth; 181b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 182b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 183b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler List<Site> getChildren() { 184b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return new ArrayList<Site>(mChildren.values()); 185b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 186b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 187b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Get the child at the given path relative to this site. 188b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Returns null if no such child found. 189b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler Site getChild(Iterator<StackFrame> path) { 190b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (path.hasNext()) { 191b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler String next = path.next().toString(); 192b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler Site child = mChildren.get(next); 193b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return (child == null) ? null : child.getChild(path); 194b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } else { 195b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return this; 196b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 197b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 198b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler} 199