From 49f2f26f3b3a79c55c1d3f6daa8e1c4917fa8303 Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Mon, 20 Jan 2014 13:00:54 -0600 Subject: [PATCH] Issue #2648 Enhance hprof output for grids and UI activity. Former-commit-id: aae0dd9677d33fbe3ec49185bfb7368939406bf2 [formerly 31bbdb3d4debe5c97f17199cbf24c3a1c5cb9a5f] [formerly 91270be4f7d4dea1ccc6533ed5ae3dd97e81a5eb] [formerly a401c4bed057230dbff78fe419a782a9bbb59014 [formerly 91270be4f7d4dea1ccc6533ed5ae3dd97e81a5eb [formerly 80e4b1bdff46f8e1c77ba50b696e8bef5e53d51e]]] Former-commit-id: a401c4bed057230dbff78fe419a782a9bbb59014 Former-commit-id: bbe5ca014327b356aa992a01543461da5e29ab6e [formerly f4075f5fa5c15128746ca6dc3a18aa314694b48c] Former-commit-id: eccaf37aee4ffed39d621421163504f4809ff853 --- .../src/com/raytheon/hprof/Id.java | 9 + .../src/com/raytheon/hprof/SmartInstance.java | 9 +- .../raytheon/uf/viz/hprof/CaveExporter.java | 3 +- .../uf/viz/hprof/D2DGridResourceExporter.java | 237 +++++++++++++----- .../viz/hprof/DisplayedResourcesExporter.java | 22 +- .../viz/hprof/DisposingResourceExporter.java | 83 ++++++ .../uf/viz/hprof/UIRunnablesExporter.java | 88 +++++++ 7 files changed, 381 insertions(+), 70 deletions(-) create mode 100644 javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/DisposingResourceExporter.java create mode 100644 javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/UIRunnablesExporter.java diff --git a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/hprof/Id.java b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/hprof/Id.java index f13dbbcf3d..2910c7d068 100644 --- a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/hprof/Id.java +++ b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/hprof/Id.java @@ -55,6 +55,15 @@ public class Id implements Comparable { buffer.get(id); } + public boolean isNull() { + for (byte b : id) { + if (b != 0x00) { + return false; + } + } + return true; + } + public int size() { return id.length; } diff --git a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/hprof/SmartInstance.java b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/hprof/SmartInstance.java index 55b033cccf..5bb32dda85 100644 --- a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/hprof/SmartInstance.java +++ b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/hprof/SmartInstance.java @@ -114,6 +114,10 @@ public class SmartInstance { return type; } + public boolean getBoolean(String fieldName) { + return getTypeNotNull(fieldName).getBoolean(); + } + public int getInt(String fieldName) { return getTypeNotNull(fieldName).getInt(); } @@ -183,7 +187,8 @@ public class SmartInstance { public String getString(String fieldName) { Id fieldId = getId(fieldName); if (fieldId == null) { - return null; + throw new IllegalStateException(fieldName + + " is not a a valid field"); } InstanceDump field = hprof.getHeapDump().getInstance(fieldId); if (field != null) { @@ -192,6 +197,8 @@ public class SmartInstance { throw new IllegalStateException(fieldName + " is not a String."); } return smartField.toString(); + } else if (fieldId.isNull()) { + return null; } else { Iterator classDumps = hprof.getHeapDump() .getClassDumps(); diff --git a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/CaveExporter.java b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/CaveExporter.java index d8c61ebed8..ea11bf5e7b 100644 --- a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/CaveExporter.java +++ b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/CaveExporter.java @@ -81,6 +81,7 @@ public class CaveExporter { new InputHandlerExporter(hprof, outputDir).export(); new D2DProcedureDialogExporter(hprof, outputDir).export(); new GFEResourceExporter(hprof, outputDir).export(); - + new DisposingResourceExporter(hprof, outputDir).export(); + new UIRunnablesExporter(hprof, outputDir).export(); } } diff --git a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/D2DGridResourceExporter.java b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/D2DGridResourceExporter.java index 839bd4cbc4..493bb6d28c 100644 --- a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/D2DGridResourceExporter.java +++ b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/D2DGridResourceExporter.java @@ -53,7 +53,7 @@ import com.raytheon.hprof.SmartInstance; */ public class D2DGridResourceExporter extends RequestableResourceExporter { - private final boolean useDataMap = false; + private static final boolean useDataMap = false; public D2DGridResourceExporter(HprofFile hprof, File outputDirectory) { super(hprof, outputDirectory, null); @@ -93,45 +93,58 @@ public class D2DGridResourceExporter extends RequestableResourceExporter { } println("# Section 2 size and type of all GeneralGridData."); Map sizes = new HashMap(); - if (useDataMap) { - for (SmartInstance resource : resources) { - int floats = 0; + for (SmartInstance resource : resources) { + int floats = 0; + List datas = new ArrayList(); + if (useDataMap) { ConcurrentHashMap dataMap = resource .get("dataMap").toConcurrentHashMap(); - if (!dataMap.isEmpty()) { - println(resource + "{"); - for (Entry dataEntry : dataMap - .entrySet()) { - List dataList = dataEntry.getValue() - .toArrayList(); - for (SmartInstance gridData : dataList) { - floats += outputGeneralGridData(gridData); - } + for (Entry dataEntry : dataMap + .entrySet()) { + List dataList = dataEntry.getValue() + .toArrayList(); + for (SmartInstance gridData : dataList) { + datas.add(new GeneralGridDataInstance(gridData)); } - println("}"); } - sizes.put(resource, floats); - } - } else { - for (SmartInstance resource : resources) { - int floats = 0; + } else { ArrayList requests = resource.get("requestJob") .get("requests").toArrayList(); - if (!requests.isEmpty()) { - println(resource + "{"); - for (SmartInstance request : requests) { - SmartInstance data = request.get("gridData"); - if (data != null) { - List dataList = data.toArrayList(); - for (SmartInstance gridData : dataList) { - floats += outputGeneralGridData(gridData); - } + for (SmartInstance request : requests) { + SmartInstance data = request.get("gridData"); + if (data != null) { + List dataList = data.toArrayList(); + for (SmartInstance gridData : dataList) { + datas.add(new GeneralGridDataInstance(gridData)); } } - println("}"); } - sizes.put(resource, floats); } + if (datas.isEmpty()) { + continue; + } + println(resource + "{"); + + Map redundantCounts = new HashMap(); + + for (GeneralGridDataInstance gridDataInst : datas) { + int count = 0; + if (redundantCounts.containsKey(gridDataInst)) { + count = redundantCounts.get(gridDataInst); + } + count += 1; + redundantCounts.put(gridDataInst, count); + floats += gridDataInst.getFloatCount(); + } + for (Entry entry : redundantCounts + .entrySet()) { + sizes.put(resource, floats); + println(" " + entry.getValue() + + " instances of GeneralGridData like {"); + println(entry.getKey().toString()); + println(" }"); + } + println("}"); } println("# Section 3 total size of each resource."); List> sizesList = new ArrayList>( @@ -148,6 +161,23 @@ public class D2DGridResourceExporter extends RequestableResourceExporter { int totalFloats = 0; for (Entry entry : sizesList) { SmartInstance resource = entry.getKey(); + StringBuilder modHint = new StringBuilder(); + try { + boolean dataModified = resource.getBoolean("dataModified"); + modHint.append("(dataModified=").append(dataModified) + .append(")"); + } catch (IllegalStateException e) { + /* heap dump is from before 14.2 */ + } + try { + boolean reprojectedData = resource + .getBoolean("reprojectedData"); + modHint.append("(reprojectedData=").append(reprojectedData) + .append(")"); + } catch (IllegalStateException e) { + /* heap dump is from after 14.2 */ + } + resource.getBoolean("reprojectedData"); int floats = entry.getValue(); int size = floats * 4 / 1024; String suffix = "KB"; @@ -155,7 +185,8 @@ public class D2DGridResourceExporter extends RequestableResourceExporter { size /= 1024; suffix = "MB"; } - println(resource + " uses is " + size + suffix); + println(resource.toString() + modHint.toString() + " uses is " + + size + suffix); totalFloats += floats; } println("# Section 4 total size of all resources."); @@ -163,44 +194,122 @@ public class D2DGridResourceExporter extends RequestableResourceExporter { + " resources is " + totalFloats * 4 / 1024 / 1024 + "MB"); } - protected int outputGeneralGridData(SmartInstance generalGridData) - throws IOException { - println(" " + generalGridData + "{"); - SmartInstance gridGeometry = generalGridData.get("gridGeometry"); - SmartInstance gridRange = gridGeometry.get("gridRange"); - int[] index = gridRange.getIntArray("index"); - int width = index[2] - index[0]; - int height = index[3] - index[1]; - println(" dimensions are " + width + "x" + height + ""); + private static class GeneralGridDataInstance { + + private final int width; + + private final int height; + + /* number of floats */ + private final int scalarCapacity; + + /* number of floats */ + private final int dirCapacity; + + /* number of floats */ + private final int uCapacity; + + /* number of floats */ + private final int vCapacity; + + public GeneralGridDataInstance(SmartInstance generalGridData) { + SmartInstance gridGeometry = generalGridData.get("gridGeometry"); + SmartInstance gridRange = gridGeometry.get("gridRange"); + int[] index = gridRange.getIntArray("index"); + width = index[2] - index[0]; + height = index[3] - index[1]; + + SmartInstance buffer = generalGridData.get("scalarData"); + scalarCapacity = getCapacity(buffer); + + buffer = generalGridData.get("direction"); + dirCapacity = getCapacity(buffer); + + buffer = generalGridData.get("uComponent"); + uCapacity = getCapacity(buffer); + + buffer = generalGridData.get("vComponent"); + vCapacity = getCapacity(buffer); - int floats = 0; - SmartInstance buffer = generalGridData.get("scalarData"); - if (buffer != null) { - int capacity = buffer.getInt("capacity"); - println(" scalarData contains " + capacity + " floats."); - floats += capacity; } - buffer = generalGridData.get("direction"); - if (buffer != null) { - int capacity = buffer.getInt("capacity"); - println(" direction contains " + capacity + " floats."); - floats += capacity; + + private static int getCapacity(SmartInstance buffer) { + if (buffer == null) { + return 0; + } + try { + return buffer.getInt("capacity"); + } catch (IllegalStateException e) { + return buffer.get("buffer").getInt("capacity"); + } } - buffer = generalGridData.get("uComponent"); - if (buffer != null) { - int capacity = buffer.getInt("capacity"); - println(" uComponent contains " + capacity + " floats."); - floats += capacity; + + public int getFloatCount() { + return uCapacity + vCapacity + scalarCapacity + dirCapacity; } - buffer = generalGridData.get("vComponent"); - if (buffer != null) { - int capacity = buffer.getInt("capacity"); - println(" vComponent contains " + capacity + " floats."); - floats += capacity; + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append(" dimensions are " + width + "x" + height + "\n"); + if (scalarCapacity != 0) { + str.append(" scalarData contains " + scalarCapacity + + " floats.\n"); + } + if (dirCapacity != 0) { + str.append(" direction contains " + dirCapacity + + " floats.\n"); + } + if (uCapacity != 0) { + str.append(" uComponent contains " + uCapacity + + " floats.\n"); + } + if (vCapacity != 0) { + str.append(" vComponent contains " + vCapacity + + " floats.\n"); + } + str.append(" memory usage is " + getFloatCount() * 4 / 1024 + + "KB"); + return str.toString(); } - println(" memory usage is " + floats * 4 / 1024 + "KB"); - println(" }"); - return floats; + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + dirCapacity; + result = prime * result + height; + result = prime * result + scalarCapacity; + result = prime * result + uCapacity; + result = prime * result + vCapacity; + result = prime * result + width; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + GeneralGridDataInstance other = (GeneralGridDataInstance) obj; + if (dirCapacity != other.dirCapacity) + return false; + if (height != other.height) + return false; + if (scalarCapacity != other.scalarCapacity) + return false; + if (uCapacity != other.uCapacity) + return false; + if (vCapacity != other.vCapacity) + return false; + if (width != other.width) + return false; + return true; + } + } } diff --git a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/DisplayedResourcesExporter.java b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/DisplayedResourcesExporter.java index c713f954de..153eb81d2f 100644 --- a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/DisplayedResourcesExporter.java +++ b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/DisplayedResourcesExporter.java @@ -71,13 +71,26 @@ public class DisplayedResourcesExporter extends DisplayPaneContainerExporter { } @Override - protected void outputPaneManager( - SmartInstance paneManager) throws IOException { + protected void outputPaneManager(SmartInstance paneManager) + throws IOException { List displayPanes = paneManager.get("displayPanes") .toArrayList(); for (SmartInstance dispalyPane : displayPanes) { - SmartInstance descriptor = dispalyPane.get("renderableDisplay") - .get("descriptor"); + SmartInstance renderableDisplay = dispalyPane + .get("renderableDisplay"); + try { + String scale = renderableDisplay.getString("scaleName"); + println(" scaleName = " + scale); + } catch (IllegalStateException e) { + /* Not D2D or after 14.2 */ + } + try { + String scale = renderableDisplay.getString("scale"); + println(" scale = " + scale); + } catch (IllegalStateException e) { + /* Not D2D or before 14.2 */ + } + SmartInstance descriptor = renderableDisplay.get("descriptor"); SmartInstance resourceList = descriptor.get("resourceList"); SmartInstance[] array = resourceList.getObjectArray("array"); println(" " + descriptor + "{"); @@ -99,6 +112,7 @@ public class DisplayedResourcesExporter extends DisplayPaneContainerExporter { println(" }"); } } + public List getResources() { return resources; } diff --git a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/DisposingResourceExporter.java b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/DisposingResourceExporter.java new file mode 100644 index 0000000000..509d05a981 --- /dev/null +++ b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/DisposingResourceExporter.java @@ -0,0 +1,83 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.hprof; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import com.raytheon.hprof.HprofFile; +import com.raytheon.hprof.SmartInstance; + +/** + * + * Export information about the resources waiting to dispose. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jan 20, 2014  2648     bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class DisposingResourceExporter extends AbstractExporter { + + public DisposingResourceExporter(HprofFile hprof, File outputDirectory) { + super(hprof, outputDirectory); + } + + @Override + protected String getFileName() { + return "disposingResources.txt"; + } + + @Override + protected String getComment() { + StringBuilder comment = new StringBuilder(); + comment.append("# This file contains resources that are waiting for the ResourceCatalog to\n"); + comment.append("# dispose them. These resources have already been removed from displays and are\n"); + comment.append("# waiting for asyncronous access to the UI thread."); + return comment.toString(); + } + + @Override + protected String getInfo() { + return "Generating output for disposing Resources..."; + } + + @Override + protected void exportInternal() throws IOException { + List runnables = getInstances("com.raytheon.uf.viz.core.rsc.ResourceCatalog$1"); + if (runnables.isEmpty()) { + return; + } + for (SmartInstance runnable : runnables) { + SmartInstance resource = runnable.get("val$resource"); + println(resource.toString()); + } + } + +} diff --git a/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/UIRunnablesExporter.java b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/UIRunnablesExporter.java new file mode 100644 index 0000000000..7ad2a458c9 --- /dev/null +++ b/javaUtilities/com.raytheon.uf.viz.hprof/src/com/raytheon/uf/viz/hprof/UIRunnablesExporter.java @@ -0,0 +1,88 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.hprof; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import com.raytheon.hprof.HprofFile; +import com.raytheon.hprof.SmartInstance; + +/** + * + * Export information about the runnables waiting to execute on the UI Thread. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jan 20, 2014  2648     bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class UIRunnablesExporter extends AbstractExporter { + + public UIRunnablesExporter(HprofFile hprof, File outputDirectory) { + super(hprof, outputDirectory); + } + + @Override + protected String getFileName() { + return "uiRunnables.txt"; + } + + @Override + protected String getComment() { + StringBuilder comment = new StringBuilder(); + comment.append("# This file contains runnables waiting for access to the SWT UI Thread. These are\n"); + comment.append("# often scheduled through VizApp.runAsync."); + return comment.toString(); + } + + @Override + protected String getInfo() { + return "Generating output for UI Runnables..."; + } + + @Override + protected void exportInternal() throws IOException { + List displays = getInstances("org.eclipse.swt.widgets.Display"); + if (displays.isEmpty()) { + return; + } + println(displays.size() + " dispaly(s)"); + for (SmartInstance display : displays) { + SmartInstance[] messages = display.get("synchronizer") + .getObjectArray("messages"); + println(messages.length + " message(s)"); + for (SmartInstance message : messages) { + println(message.get("runnable").toString()); + } + + } + } + +}