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