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.Heap; 20b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.io.IOException; 21b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.util.Collections; 22b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.util.Comparator; 23b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.util.List; 24b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 251af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhlerclass SiteHandler implements AhatHandler { 261af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler private static final String ALLOCATION_SITE_ID = "frames"; 271af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler private static final String SITES_CALLED_ID = "called"; 281af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler private static final String OBJECTS_ALLOCATED_ID = "objects"; 291af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler 301af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler private AhatSnapshot mSnapshot; 311af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler 32b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public SiteHandler(AhatSnapshot snapshot) { 331af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler mSnapshot = snapshot; 34b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 35b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 36b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler @Override 37b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public void handle(Doc doc, Query query) throws IOException { 38b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler int stackId = query.getInt("stack", 0); 39b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler int depth = query.getInt("depth", -1); 40b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler Site site = mSnapshot.getSite(stackId, depth); 41b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 42b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler doc.title("Site %s", site.getName()); 43b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler doc.section("Allocation Site"); 441af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler SitePrinter.printSite(mSnapshot, doc, query, ALLOCATION_SITE_ID, site); 45b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 46b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler doc.section("Sites Called from Here"); 47b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler List<Site> children = site.getChildren(); 48b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (children.isEmpty()) { 49b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler doc.println(DocString.text("(none)")); 50b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } else { 51b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler Collections.sort(children, new Sort.SiteBySize("app")); 52b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 53b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler HeapTable.TableConfig<Site> table = new HeapTable.TableConfig<Site>() { 54b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public String getHeapsDescription() { 55b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return "Reachable Bytes Allocated on Heap"; 56b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 57b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 58b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public long getSize(Site element, Heap heap) { 59b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return element.getSize(heap.getName()); 60b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 61b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 62b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public List<HeapTable.ValueConfig<Site>> getValueConfigs() { 63b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler HeapTable.ValueConfig<Site> value = new HeapTable.ValueConfig<Site>() { 64b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public String getDescription() { 65b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return "Child Site"; 66b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 67b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 68b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler public DocString render(Site element) { 69b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return DocString.link( 70c21e4e67861f38e2ebce3cce633d01fcb8de5f1fRichard Uhler DocString.formattedUri("site?stack=%d&depth=%d", 71b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler element.getStackId(), element.getStackDepth()), 72b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler DocString.text(element.getName())); 73b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 74b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler }; 75b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return Collections.singletonList(value); 76b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 77b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler }; 781af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler HeapTable.render(doc, query, SITES_CALLED_ID, table, mSnapshot, children); 79b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 80b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 81b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler doc.section("Objects Allocated"); 82b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler doc.table( 83b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler new Column("Reachable Bytes Allocated", Column.Align.RIGHT), 84b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler new Column("Instances", Column.Align.RIGHT), 85b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler new Column("Heap"), 86b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler new Column("Class")); 87b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler List<Site.ObjectsInfo> infos = site.getObjectsInfos(); 88b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler Comparator<Site.ObjectsInfo> compare = new Sort.WithPriority<Site.ObjectsInfo>( 89b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler new Sort.ObjectsInfoByHeapName(), 90b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler new Sort.ObjectsInfoBySize(), 91b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler new Sort.ObjectsInfoByClassName()); 92b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler Collections.sort(infos, compare); 931af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler SubsetSelector<Site.ObjectsInfo> selector 941af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler = new SubsetSelector(query, OBJECTS_ALLOCATED_ID, infos); 951af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler for (Site.ObjectsInfo info : selector.selected()) { 96b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler String className = AhatSnapshot.getClassName(info.classObj); 97b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler doc.row( 98c21e4e67861f38e2ebce3cce633d01fcb8de5f1fRichard Uhler DocString.format("%,14d", info.numBytes), 99b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler DocString.link( 100c21e4e67861f38e2ebce3cce633d01fcb8de5f1fRichard Uhler DocString.formattedUri("objects?stack=%d&depth=%d&heap=%s&class=%s", 101b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler site.getStackId(), site.getStackDepth(), info.heap.getName(), className), 102c21e4e67861f38e2ebce3cce633d01fcb8de5f1fRichard Uhler DocString.format("%,14d", info.numInstances)), 103b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler DocString.text(info.heap.getName()), 10438f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler Value.render(mSnapshot, info.classObj)); 105b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 106b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler doc.end(); 1071af86f17dc9a47faf1c6cd7ccd23d248fdc615abRichard Uhler selector.render(doc); 108b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 109b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler} 110b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 111