Home | History | Annotate | Download | only in src
      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