• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Heap;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 
25 /**
26  * Class for rendering a table that includes sizes of some kind for each heap.
27  */
28 class HeapTable {
29   /**
30    * Configuration for a value column of a heap table.
31    */
32   public interface ValueConfig<T> {
getDescription()33     String getDescription();
render(T element)34     DocString render(T element);
35   }
36 
37   /**
38    * Configuration for the HeapTable.
39    */
40   public interface TableConfig<T> {
getHeapsDescription()41     String getHeapsDescription();
getSize(T element, Heap heap)42     long getSize(T element, Heap heap);
getValueConfigs()43     List<ValueConfig<T>> getValueConfigs();
44   }
45 
46   /**
47    * Render the table to the given document.
48    * @param query - The page query.
49    * @param id - A unique identifier for the table on the page.
50    */
render(Doc doc, Query query, String id, TableConfig<T> config, AhatSnapshot snapshot, List<T> elements)51   public static <T> void render(Doc doc, Query query, String id,
52       TableConfig<T> config, AhatSnapshot snapshot, List<T> elements) {
53     // Only show the heaps that have non-zero entries.
54     List<Heap> heaps = new ArrayList<Heap>();
55     for (Heap heap : snapshot.getHeaps()) {
56       if (hasNonZeroEntry(snapshot, heap, config, elements)) {
57         heaps.add(heap);
58       }
59     }
60 
61     List<ValueConfig<T>> values = config.getValueConfigs();
62 
63     // Print the heap and values descriptions.
64     boolean showTotal = heaps.size() > 1;
65     List<Column> subcols = new ArrayList<Column>();
66     for (Heap heap : heaps) {
67       subcols.add(new Column(heap.getName(), Column.Align.RIGHT));
68     }
69     if (showTotal) {
70       subcols.add(new Column("Total", Column.Align.RIGHT));
71     }
72     List<Column> cols = new ArrayList<Column>();
73     for (ValueConfig value : values) {
74       cols.add(new Column(value.getDescription()));
75     }
76     doc.table(DocString.text(config.getHeapsDescription()), subcols, cols);
77 
78     // Print the entries up to the selected limit.
79     SubsetSelector<T> selector = new SubsetSelector(query, id, elements);
80     ArrayList<DocString> vals = new ArrayList<DocString>();
81     for (T elem : selector.selected()) {
82       vals.clear();
83       long total = 0;
84       for (Heap heap : heaps) {
85         long size = config.getSize(elem, heap);
86         total += size;
87         vals.add(DocString.format("%,14d", size));
88       }
89       if (showTotal) {
90         vals.add(DocString.format("%,14d", total));
91       }
92 
93       for (ValueConfig<T> value : values) {
94         vals.add(value.render(elem));
95       }
96       doc.row(vals.toArray(new DocString[0]));
97     }
98 
99     // Print a summary of the remaining entries if there are any.
100     List<T> remaining = selector.remaining();
101     if (!remaining.isEmpty()) {
102       Map<Heap, Long> summary = new HashMap<Heap, Long>();
103       for (Heap heap : heaps) {
104         summary.put(heap, 0L);
105       }
106 
107       for (T elem : remaining) {
108         for (Heap heap : heaps) {
109           summary.put(heap, summary.get(heap) + config.getSize(elem, heap));
110         }
111       }
112 
113       vals.clear();
114       long total = 0;
115       for (Heap heap : heaps) {
116         long size = summary.get(heap);
117         total += size;
118         vals.add(DocString.format("%,14d", size));
119       }
120       if (showTotal) {
121         vals.add(DocString.format("%,14d", total));
122       }
123 
124       for (ValueConfig<T> value : values) {
125         vals.add(DocString.text("..."));
126       }
127       doc.row(vals.toArray(new DocString[0]));
128     }
129     doc.end();
130     selector.render(doc);
131   }
132 
133   // Returns true if the given heap has a non-zero size entry.
hasNonZeroEntry(AhatSnapshot snapshot, Heap heap, TableConfig<T> config, List<T> elements)134   public static <T> boolean hasNonZeroEntry(AhatSnapshot snapshot, Heap heap,
135       TableConfig<T> config, List<T> elements) {
136     if (snapshot.getHeapSize(heap) > 0) {
137       for (T element : elements) {
138         if (config.getSize(element, heap) > 0) {
139           return true;
140         }
141       }
142     }
143     return false;
144   }
145 }
146 
147