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.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> {
     33     String getDescription();
     34     DocString render(T element);
     35   }
     36 
     37   /**
     38    * Configuration for the HeapTable.
     39    */
     40   public interface TableConfig<T> {
     41     String getHeapsDescription();
     42     long getSize(T element, Heap heap);
     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    */
     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.
    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