ahat: limit default number of results shown.
Previously, ahat had performance issues rendering large pages. This
change causes ahat to limit the number results shown in large pages by
default, requiring the user to explicitly request more information if
they care about it.
Bug: 25114227
Change-Id: Ief67396be254be4c84e6971f5b903a701206e17b
diff --git a/tools/ahat/src/ObjectHandler.java b/tools/ahat/src/ObjectHandler.java
index 5e321e2..9e4ce56 100644
--- a/tools/ahat/src/ObjectHandler.java
+++ b/tools/ahat/src/ObjectHandler.java
@@ -25,13 +25,26 @@
import com.android.tools.perflib.heap.RootObj;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-class ObjectHandler extends AhatHandler {
+class ObjectHandler implements AhatHandler {
+
+ private static final String ARRAY_ELEMENTS_ID = "elements";
+ private static final String DOMINATOR_PATH_ID = "dompath";
+ private static final String ALLOCATION_SITE_ID = "frames";
+ private static final String DOMINATED_OBJECTS_ID = "dominated";
+ private static final String INSTANCE_FIELDS_ID = "ifields";
+ private static final String STATIC_FIELDS_ID = "sfields";
+ private static final String HARD_REFS_ID = "refs";
+ private static final String SOFT_REFS_ID = "srefs";
+
+ private AhatSnapshot mSnapshot;
+
public ObjectHandler(AhatSnapshot snapshot) {
- super(snapshot);
+ mSnapshot = snapshot;
}
@Override
@@ -46,8 +59,8 @@
doc.title("Object %08x", inst.getUniqueId());
doc.big(Value.render(inst));
- printAllocationSite(doc, inst);
- printDominatorPath(doc, inst);
+ printAllocationSite(doc, query, inst);
+ printDominatorPath(doc, query, inst);
doc.section("Object Info");
ClassObj cls = inst.getClassObj();
@@ -62,39 +75,46 @@
printBitmap(doc, inst);
if (inst instanceof ClassInstance) {
- printClassInstanceFields(doc, (ClassInstance)inst);
+ printClassInstanceFields(doc, query, (ClassInstance)inst);
} else if (inst instanceof ArrayInstance) {
- printArrayElements(doc, (ArrayInstance)inst);
+ printArrayElements(doc, query, (ArrayInstance)inst);
} else if (inst instanceof ClassObj) {
- printClassInfo(doc, (ClassObj)inst);
+ printClassInfo(doc, query, (ClassObj)inst);
}
- printReferences(doc, inst);
+ printReferences(doc, query, inst);
printDominatedObjects(doc, query, inst);
}
- private static void printClassInstanceFields(Doc doc, ClassInstance inst) {
+ private static void printClassInstanceFields(Doc doc, Query query, ClassInstance inst) {
doc.section("Fields");
doc.table(new Column("Type"), new Column("Name"), new Column("Value"));
- for (ClassInstance.FieldValue field : inst.getValues()) {
+ SubsetSelector<ClassInstance.FieldValue> selector
+ = new SubsetSelector(query, INSTANCE_FIELDS_ID, inst.getValues());
+ for (ClassInstance.FieldValue field : selector.selected()) {
doc.row(
DocString.text(field.getField().getType().toString()),
DocString.text(field.getField().getName()),
Value.render(field.getValue()));
}
doc.end();
+ selector.render(doc);
}
- private static void printArrayElements(Doc doc, ArrayInstance array) {
+ private static void printArrayElements(Doc doc, Query query, ArrayInstance array) {
doc.section("Array Elements");
doc.table(new Column("Index", Column.Align.RIGHT), new Column("Value"));
- Object[] elements = array.getValues();
- for (int i = 0; i < elements.length; i++) {
- doc.row(DocString.format("%d", i), Value.render(elements[i]));
+ List<Object> elements = Arrays.asList(array.getValues());
+ SubsetSelector<Object> selector = new SubsetSelector(query, ARRAY_ELEMENTS_ID, elements);
+ int i = 0;
+ for (Object elem : selector.selected()) {
+ doc.row(DocString.format("%d", i), Value.render(elem));
+ i++;
}
doc.end();
+ selector.render(doc);
}
- private static void printClassInfo(Doc doc, ClassObj clsobj) {
+ private static void printClassInfo(Doc doc, Query query, ClassObj clsobj) {
doc.section("Class Info");
doc.descriptions();
doc.description(DocString.text("Super Class"), Value.render(clsobj.getSuperClassObj()));
@@ -103,41 +123,52 @@
doc.section("Static Fields");
doc.table(new Column("Type"), new Column("Name"), new Column("Value"));
- for (Map.Entry<Field, Object> field : clsobj.getStaticFieldValues().entrySet()) {
+ List<Map.Entry<Field, Object>> fields
+ = new ArrayList<Map.Entry<Field, Object>>(clsobj.getStaticFieldValues().entrySet());
+ SubsetSelector<Map.Entry<Field, Object>> selector
+ = new SubsetSelector(query, STATIC_FIELDS_ID, fields);
+ for (Map.Entry<Field, Object> field : selector.selected()) {
doc.row(
DocString.text(field.getKey().getType().toString()),
DocString.text(field.getKey().getName()),
Value.render(field.getValue()));
}
doc.end();
+ selector.render(doc);
}
- private static void printReferences(Doc doc, Instance inst) {
+ private static void printReferences(Doc doc, Query query, Instance inst) {
doc.section("Objects with References to this Object");
if (inst.getHardReferences().isEmpty()) {
doc.println(DocString.text("(none)"));
} else {
doc.table(new Column("Object"));
- for (Instance ref : inst.getHardReferences()) {
+ List<Instance> references = inst.getHardReferences();
+ SubsetSelector<Instance> selector = new SubsetSelector(query, HARD_REFS_ID, references);
+ for (Instance ref : selector.selected()) {
doc.row(Value.render(ref));
}
doc.end();
+ selector.render(doc);
}
if (inst.getSoftReferences() != null) {
doc.section("Objects with Soft References to this Object");
doc.table(new Column("Object"));
- for (Instance ref : inst.getSoftReferences()) {
- doc.row(Value.render(inst));
+ List<Instance> references = inst.getSoftReferences();
+ SubsetSelector<Instance> selector = new SubsetSelector(query, SOFT_REFS_ID, references);
+ for (Instance ref : selector.selected()) {
+ doc.row(Value.render(ref));
}
doc.end();
+ selector.render(doc);
}
}
- private void printAllocationSite(Doc doc, Instance inst) {
+ private void printAllocationSite(Doc doc, Query query, Instance inst) {
doc.section("Allocation Site");
Site site = mSnapshot.getSiteForInstance(inst);
- SitePrinter.printSite(doc, mSnapshot, site);
+ SitePrinter.printSite(mSnapshot, doc, query, ALLOCATION_SITE_ID, site);
}
// Draw the bitmap corresponding to this instance if there is one.
@@ -150,7 +181,7 @@
}
}
- private void printDominatorPath(Doc doc, Instance inst) {
+ private void printDominatorPath(Doc doc, Query query, Instance inst) {
doc.section("Dominator Path from Root");
List<Instance> path = new ArrayList<Instance>();
for (Instance parent = inst;
@@ -193,14 +224,14 @@
return Collections.singletonList(value);
}
};
- HeapTable.render(doc, table, mSnapshot, path);
+ HeapTable.render(doc, query, DOMINATOR_PATH_ID, table, mSnapshot, path);
}
public void printDominatedObjects(Doc doc, Query query, Instance inst) {
doc.section("Immediately Dominated Objects");
List<Instance> instances = mSnapshot.getDominated(inst);
if (instances != null) {
- DominatedList.render(mSnapshot, doc, instances, query);
+ DominatedList.render(mSnapshot, doc, query, DOMINATED_OBJECTS_ID, instances);
} else {
doc.println(DocString.text("(none)"));
}