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