Title: [142074] trunk/Source/WebCore
Revision
142074
Author
[email protected]
Date
2013-02-07 00:38:04 -0800 (Thu, 07 Feb 2013)

Log Message

Web Inspector: Native Memory Instrumentation: reduce native heap snapshot runtime memory footprint
https://bugs.webkit.org/show_bug.cgi?id=108824

Reviewed by Yury Semikhatsky.

New event was added into Memory domain addNativeSnapshotChunk.
The content of HeapGraphSerializer is completely rewritten according to new API.
Now it collects strings, nodes, edges and id2id map and pushes when the collected items count exceed a limit.
On the frontend side I added new method for the new event and fixed the postprocessing step.
MemoryInstrumentation was slightly changed. Now it reports base to real address map only after reporting the node with real address.

* inspector/HeapGraphSerializer.cpp:
(WebCore::HeapGraphSerializer::HeapGraphSerializer):
(WebCore::HeapGraphSerializer::pushUpdateIfNeed):
(WebCore):
(WebCore::HeapGraphSerializer::pushUpdate):
(WebCore::HeapGraphSerializer::reportNode):
(WebCore::HeapGraphSerializer::reportNodeImpl):
(WebCore::HeapGraphSerializer::reportEdge):
(WebCore::HeapGraphSerializer::reportEdgeImpl):
(WebCore::HeapGraphSerializer::reportLeaf):
(WebCore::HeapGraphSerializer::reportBaseAddress):
(WebCore::HeapGraphSerializer::finish):
(WebCore::HeapGraphSerializer::reportMemoryUsage):
(WebCore::HeapGraphSerializer::addString):
(WebCore::HeapGraphSerializer::toNodeId):
(WebCore::HeapGraphSerializer::addRootNode):
* inspector/HeapGraphSerializer.h:
(HeapGraphSerializer):
* inspector/Inspector.json:
* inspector/InspectorController.cpp:
(WebCore::InspectorController::processMemoryDistribution):
* inspector/InspectorMemoryAgent.cpp:
(WebCore::InspectorMemoryAgent::getProcessMemoryDistributionMap):
(WebCore):
(WebCore::InspectorMemoryAgent::getProcessMemoryDistribution):
(WebCore::InspectorMemoryAgent::getProcessMemoryDistributionImpl):
(WebCore::InspectorMemoryAgent::setFrontend):
(WebCore::InspectorMemoryAgent::clearFrontend):
* inspector/InspectorMemoryAgent.h:
(InspectorMemoryAgent):
* inspector/front-end/NativeHeapSnapshot.js:
(WebInspector.NativeHeapSnapshot):
(WebInspector.NativeHeapSnapshotNode.prototype.classIndex):
(WebInspector.NativeHeapSnapshotNode.prototype.id):
(WebInspector.NativeHeapSnapshotNode.prototype.name):
(WebInspector.NativeHeapSnapshotNode.prototype.serialize):
* inspector/front-end/NativeMemorySnapshotView.js:
(WebInspector.NativeSnapshotProfileType.prototype.buttonClicked.didReceiveMemorySnapshot):
(WebInspector.NativeSnapshotProfileType.prototype.buttonClicked):
(WebInspector.NativeSnapshotProfileHeader):
(WebInspector.NativeSnapshotProfileHeader.prototype.startSnapshotTransfer):
(WebInspector.NativeSnapshotProfileHeader.prototype.addNativeSnapshotChunk):
(WebInspector.NativeMemoryProfileType.prototype.buttonClicked.didReceiveMemorySnapshot):
(WebInspector.NativeMemoryProfileType.prototype.buttonClicked):
(WebInspector.NativeMemoryBarChart.prototype._updateStats):
* inspector/front-end/ProfilesPanel.js:
(WebInspector.ProfilesPanel):
(WebInspector.MemoryDispatcher):
(WebInspector.MemoryDispatcher.prototype.addNativeSnapshotChunk):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (142073 => 142074)


--- trunk/Source/WebCore/ChangeLog	2013-02-07 08:34:11 UTC (rev 142073)
+++ trunk/Source/WebCore/ChangeLog	2013-02-07 08:38:04 UTC (rev 142074)
@@ -1,3 +1,66 @@
+2013-02-06  Ilya Tikhonovsky  <[email protected]>
+
+        Web Inspector: Native Memory Instrumentation: reduce native heap snapshot runtime memory footprint
+        https://bugs.webkit.org/show_bug.cgi?id=108824
+
+        Reviewed by Yury Semikhatsky.
+
+        New event was added into Memory domain addNativeSnapshotChunk.
+        The content of HeapGraphSerializer is completely rewritten according to new API.
+        Now it collects strings, nodes, edges and id2id map and pushes when the collected items count exceed a limit.
+        On the frontend side I added new method for the new event and fixed the postprocessing step.
+        MemoryInstrumentation was slightly changed. Now it reports base to real address map only after reporting the node with real address.
+
+        * inspector/HeapGraphSerializer.cpp:
+        (WebCore::HeapGraphSerializer::HeapGraphSerializer):
+        (WebCore::HeapGraphSerializer::pushUpdateIfNeed):
+        (WebCore):
+        (WebCore::HeapGraphSerializer::pushUpdate):
+        (WebCore::HeapGraphSerializer::reportNode):
+        (WebCore::HeapGraphSerializer::reportNodeImpl):
+        (WebCore::HeapGraphSerializer::reportEdge):
+        (WebCore::HeapGraphSerializer::reportEdgeImpl):
+        (WebCore::HeapGraphSerializer::reportLeaf):
+        (WebCore::HeapGraphSerializer::reportBaseAddress):
+        (WebCore::HeapGraphSerializer::finish):
+        (WebCore::HeapGraphSerializer::reportMemoryUsage):
+        (WebCore::HeapGraphSerializer::addString):
+        (WebCore::HeapGraphSerializer::toNodeId):
+        (WebCore::HeapGraphSerializer::addRootNode):
+        * inspector/HeapGraphSerializer.h:
+        (HeapGraphSerializer):
+        * inspector/Inspector.json:
+        * inspector/InspectorController.cpp:
+        (WebCore::InspectorController::processMemoryDistribution):
+        * inspector/InspectorMemoryAgent.cpp:
+        (WebCore::InspectorMemoryAgent::getProcessMemoryDistributionMap):
+        (WebCore):
+        (WebCore::InspectorMemoryAgent::getProcessMemoryDistribution):
+        (WebCore::InspectorMemoryAgent::getProcessMemoryDistributionImpl):
+        (WebCore::InspectorMemoryAgent::setFrontend):
+        (WebCore::InspectorMemoryAgent::clearFrontend):
+        * inspector/InspectorMemoryAgent.h:
+        (InspectorMemoryAgent):
+        * inspector/front-end/NativeHeapSnapshot.js:
+        (WebInspector.NativeHeapSnapshot):
+        (WebInspector.NativeHeapSnapshotNode.prototype.classIndex):
+        (WebInspector.NativeHeapSnapshotNode.prototype.id):
+        (WebInspector.NativeHeapSnapshotNode.prototype.name):
+        (WebInspector.NativeHeapSnapshotNode.prototype.serialize):
+        * inspector/front-end/NativeMemorySnapshotView.js:
+        (WebInspector.NativeSnapshotProfileType.prototype.buttonClicked.didReceiveMemorySnapshot):
+        (WebInspector.NativeSnapshotProfileType.prototype.buttonClicked):
+        (WebInspector.NativeSnapshotProfileHeader):
+        (WebInspector.NativeSnapshotProfileHeader.prototype.startSnapshotTransfer):
+        (WebInspector.NativeSnapshotProfileHeader.prototype.addNativeSnapshotChunk):
+        (WebInspector.NativeMemoryProfileType.prototype.buttonClicked.didReceiveMemorySnapshot):
+        (WebInspector.NativeMemoryProfileType.prototype.buttonClicked):
+        (WebInspector.NativeMemoryBarChart.prototype._updateStats):
+        * inspector/front-end/ProfilesPanel.js:
+        (WebInspector.ProfilesPanel):
+        (WebInspector.MemoryDispatcher):
+        (WebInspector.MemoryDispatcher.prototype.addNativeSnapshotChunk):
+
 2013-02-03  Kentaro Hara  <[email protected]>
 
         WebKit's focus events are UIEvents (instead of FocusEvent) and thus don't expose .relatedTarget

Modified: trunk/Source/WebCore/inspector/HeapGraphSerializer.cpp (142073 => 142074)


--- trunk/Source/WebCore/inspector/HeapGraphSerializer.cpp	2013-02-07 08:34:11 UTC (rev 142073)
+++ trunk/Source/WebCore/inspector/HeapGraphSerializer.cpp	2013-02-07 08:38:04 UTC (rev 142074)
@@ -34,7 +34,6 @@
 
 #include "HeapGraphSerializer.h"
 
-#include "InspectorValues.h"
 #include "WebCoreMemoryInstrumentation.h"
 #include <wtf/MemoryInstrumentationHashMap.h>
 #include <wtf/MemoryInstrumentationVector.h>
@@ -44,150 +43,120 @@
 
 namespace WebCore {
 
-class HeapGraphNode {
-public:
-    HeapGraphNode()
-        : m_type(0)
-        , m_size(0)
-        , m_className(0)
-        , m_name(0)
-        , m_edgeCount(0)
-    {
-    }
+HeapGraphSerializer::HeapGraphSerializer(InspectorFrontend::Memory* frontend)
+    : m_frontend(frontend)
+    , m_strings(Strings::create())
+    , m_edges(Edges::create())
+    , m_nodeEdgesCount(0)
+    , m_nodes(Nodes::create())
+    , m_baseToRealNodeIdMap(BaseToRealNodeIdMap::create())
+{
+    ASSERT(m_frontend);
+    m_strings->addItem(String()); // An empty string with 0 index.
 
-    int m_type;
-    unsigned m_size;
-    int m_className;
-    int m_name;
-    int m_edgeCount;
-    static const int s_nodeFieldCount = 5;
-};
+    memset(m_edgeTypes, 0, sizeof(m_edgeTypes));
 
-class HeapGraphEdge {
-public:
-    HeapGraphEdge()
-        : m_type(0)
-        , m_targetIndexIsKnown(false)
-        , m_toIndex(0)
-        , m_name(0)
-    {
-    }
+    m_edgeTypes[WTF::PointerMember] = addString("weak");
+    m_edgeTypes[WTF::OwnPtrMember] = addString("ownRef");
+    m_edgeTypes[WTF::RefPtrMember] = addString("countRef");
 
-    int m_type;
-    bool m_targetIndexIsKnown;
-    union {
-        const void* m_toObject;
-        int m_toIndex;
-    };
-    int m_name;
-};
+    m_unknownClassNameId = addString("unknown");
+}
 
-HeapGraphSerializer::HeapGraphSerializer()
-    : m_lastReportedEdgeIndex(0)
+HeapGraphSerializer::~HeapGraphSerializer()
 {
-    m_strings.append(String());
+}
 
-    memset(m_edgeTypes, 0, sizeof(m_edgeTypes));
+void HeapGraphSerializer::pushUpdateIfNeeded()
+{
+    static const size_t chunkSize = 100;
+    static const size_t averageEdgesPerNode = 5;
 
-    ASSERT(m_strings.size());
-    m_edgeTypes[WTF::PointerMember] = m_strings.size();
-    m_strings.append("weakRef");
+    if (m_strings->length() <= chunkSize
+        && m_nodes->length() <= chunkSize * s_nodeFieldsCount
+        && m_edges->length() <= chunkSize * averageEdgesPerNode * s_edgeFieldsCount
+        && m_baseToRealNodeIdMap->length() <= chunkSize * s_idMapEntryFieldCount)
+        return;
 
-    m_edgeTypes[WTF::OwnPtrMember] = m_strings.size();
-    m_strings.append("ownRef");
-
-    m_edgeTypes[WTF::RefPtrMember] = m_strings.size();
-    m_strings.append("countRef");
-
-    m_unknownClassNameId = addString("unknown");
+    pushUpdate();
 }
 
-HeapGraphSerializer::~HeapGraphSerializer()
+void HeapGraphSerializer::pushUpdate()
 {
+    typedef TypeBuilder::Memory::HeapSnapshotChunk HeapSnapshotChunk;
+
+    RefPtr<HeapSnapshotChunk> chunk = HeapSnapshotChunk::create()
+        .setStrings(m_strings.release())
+        .setNodes(m_nodes.release())
+        .setEdges(m_edges.release())
+        .setBaseToRealNodeId(m_baseToRealNodeIdMap.release());
+
+    m_frontend->addNativeSnapshotChunk(chunk);
+
+    m_strings = Strings::create();
+    m_edges = Edges::create();
+    m_nodes = Nodes::create();
+    m_baseToRealNodeIdMap = BaseToRealNodeIdMap::create();
 }
 
 void HeapGraphSerializer::reportNode(const WTF::MemoryObjectInfo& info)
 {
-    HeapGraphNode node;
-    node.m_type = addString(info.objectType());
-    node.m_size = info.objectSize();
-    node.m_className = info.className().isEmpty() ? m_unknownClassNameId : addString(info.className());
-    node.m_name = addString(info.name());
-    // Node is always reported after its outgoing edges and leaves.
-    node.m_edgeCount = m_edges.size() - m_lastReportedEdgeIndex;
-    m_lastReportedEdgeIndex = m_edges.size();
-
-    m_objectToNodeIndex.set(info.reportedPointer(), m_nodes.size());
+    reportNodeImpl(info, m_nodeEdgesCount);
+    m_nodeEdgesCount = 0;
     if (info.isRoot())
         m_roots.append(info.reportedPointer());
-    m_nodes.append(node);
+    pushUpdateIfNeeded();
 }
 
+int HeapGraphSerializer::reportNodeImpl(const WTF::MemoryObjectInfo& info, int edgesCount)
+{
+    int nodeId = toNodeId(info.reportedPointer());
+
+    m_nodes->addItem(info.className().isEmpty() ? m_unknownClassNameId : addString(info.className()));
+    m_nodes->addItem(addString(info.name()));
+    m_nodes->addItem(nodeId);
+    m_nodes->addItem(info.objectSize());
+    m_nodes->addItem(edgesCount);
+
+    return nodeId;
+}
+
 void HeapGraphSerializer::reportEdge(const void* to, const char* name, WTF::MemberType memberType)
 {
-    HeapGraphEdge edge;
     ASSERT(to);
+    reportEdgeImpl(toNodeId(to), name, m_edgeTypes[memberType]);
+    pushUpdateIfNeeded();
+}
+
+void HeapGraphSerializer::reportEdgeImpl(const int toNodeId, const char* name, int memberType)
+{
     ASSERT(memberType >= 0);
     ASSERT(memberType < WTF::LastMemberTypeEntry);
-    edge.m_type = m_edgeTypes[memberType];
-    edge.m_toObject = to;
-    edge.m_name = addString(name);
-    m_edges.append(edge);
+
+    m_edges->addItem(memberType);
+    m_edges->addItem(addString(name));
+    m_edges->addItem(toNodeId);
+
+    ++m_nodeEdgesCount;
 }
 
 void HeapGraphSerializer::reportLeaf(const WTF::MemoryObjectInfo& info, const char* edgeName)
 {
-    HeapGraphNode node;
-    node.m_type = addString(info.objectType());
-    node.m_size = info.objectSize();
-    node.m_className = addString(info.className());
-    node.m_name = addString(info.name());
-
-    int nodeIndex = m_nodes.size();
-    m_nodes.append(node);
-
-    HeapGraphEdge edge;
-    edge.m_type = m_edgeTypes[WTF::OwnPtrMember];
-    edge.m_toIndex = nodeIndex;
-    edge.m_targetIndexIsKnown = true;
-    edge.m_name = addString(edgeName);
-    m_edges.append(edge);
+    int nodeId = reportNodeImpl(info, 0);
+    reportEdgeImpl(nodeId, edgeName, m_edgeTypes[WTF::OwnPtrMember]);
+    pushUpdateIfNeeded();
 }
 
 void HeapGraphSerializer::reportBaseAddress(const void* base, const void* real)
 {
-    m_baseToRealAddress.set(base, real);
+    m_baseToRealNodeIdMap->addItem(toNodeId(base));
+    m_baseToRealNodeIdMap->addItem(toNodeId(real));
 }
 
-PassRefPtr<InspectorObject> HeapGraphSerializer::serialize()
+void HeapGraphSerializer::finish()
 {
     addRootNode();
-    adjutEdgeTargets();
-    RefPtr<InspectorArray> nodes = InspectorArray::create();
-    for (size_t i = 0; i < m_nodes.size(); i++) {
-        HeapGraphNode& node = m_nodes[i];
-        nodes->pushInt(node.m_type);
-        nodes->pushInt(node.m_className);
-        nodes->pushInt(node.m_name);
-        nodes->pushInt(node.m_size);
-        nodes->pushInt(node.m_edgeCount);
-    }
-    RefPtr<InspectorArray> edges = InspectorArray::create();
-    for (size_t i = 0; i < m_edges.size(); i++) {
-        HeapGraphEdge& edge = m_edges[i];
-        edges->pushInt(edge.m_type);
-        edges->pushInt(edge.m_name);
-        edges->pushInt(edge.m_toIndex * HeapGraphNode::s_nodeFieldCount);
-    }
-    RefPtr<InspectorArray> strings = InspectorArray::create();
-    for (size_t i = 0; i < m_strings.size(); i++)
-        strings->pushString(m_strings[i]);
-
-    RefPtr<InspectorObject> graph = InspectorObject::create();
-    graph->setArray("nodes", nodes);
-    graph->setArray("edges", edges);
-    graph->setArray("strings", strings);
-    return graph.release();
+    pushUpdate();
 }
 
 void HeapGraphSerializer::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
@@ -195,10 +164,9 @@
     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Inspector);
     info.addMember(m_stringToIndex, "stringToIndex");
     info.addMember(m_strings, "strings");
-    info.addMember(m_objectToNodeIndex, "objectToNodeIndex");
-    info.addMember(m_baseToRealAddress, "baseToRealAddress");
-    info.addMember(m_nodes, "nodes");
     info.addMember(m_edges, "edges");
+    info.addMember(m_nodes, "nodes");
+    info.addMember(m_baseToRealNodeIdMap, "baseToRealNodeIdMap");
     info.addMember(m_roots, "roots");
 }
 
@@ -206,34 +174,29 @@
 {
     if (string.isEmpty())
         return 0;
-    StringMap::AddResult result = m_stringToIndex.add(string, m_strings.size());
+    StringMap::AddResult result = m_stringToIndex.add(string, m_stringToIndex.size() + 1);
     if (result.isNewEntry)
-        m_strings.append(string);
+        m_strings->addItem(string);
     return result.iterator->value;
 }
 
-void HeapGraphSerializer::addRootNode()
+int HeapGraphSerializer::toNodeId(const void* to)
 {
-    for (size_t i = 0; i < m_roots.size(); i++)
-        reportEdge(m_roots[i], 0, WTF::PointerMember);
-    HeapGraphNode node;
-    node.m_name = addString("Root");
-    node.m_edgeCount = m_edges.size() - m_lastReportedEdgeIndex;
-    m_lastReportedEdgeIndex = m_edges.size();
-    m_nodes.append(node);
+    ASSERT(to);
+    Address2NodeId::AddResult result = m_address2NodeIdMap.add(to, m_address2NodeIdMap.size());
+    return result.iterator->value;
 }
 
-void HeapGraphSerializer::adjutEdgeTargets()
+void HeapGraphSerializer::addRootNode()
 {
-    for (size_t i = 0; i < m_edges.size(); i++) {
-        HeapGraphEdge& edge = m_edges[i];
-        if (edge.m_targetIndexIsKnown)
-            continue;
-        const void* realTarget = m_baseToRealAddress.get(edge.m_toObject);
-        if (!realTarget)
-            realTarget = edge.m_toObject;
-        edge.m_toIndex = m_objectToNodeIndex.get(realTarget);
-    }
+    for (size_t i = 0; i < m_roots.size(); i++)
+        reportEdgeImpl(toNodeId(m_roots[i]), 0, m_edgeTypes[WTF::PointerMember]);
+
+    m_nodes->addItem(addString("Root"));
+    m_nodes->addItem(0);
+    m_nodes->addItem(m_address2NodeIdMap.size());
+    m_nodes->addItem(0);
+    m_nodes->addItem(m_roots.size());
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/inspector/HeapGraphSerializer.h (142073 => 142074)


--- trunk/Source/WebCore/inspector/HeapGraphSerializer.h	2013-02-07 08:34:11 UTC (rev 142073)
+++ trunk/Source/WebCore/inspector/HeapGraphSerializer.h	2013-02-07 08:38:04 UTC (rev 142074)
@@ -33,6 +33,7 @@
 
 #if ENABLE(INSPECTOR)
 
+#include "InspectorFrontend.h"
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/MemoryInstrumentation.h>
@@ -49,35 +50,52 @@
 class HeapGraphSerializer {
     WTF_MAKE_NONCOPYABLE(HeapGraphSerializer);
 public:
-    HeapGraphSerializer();
+    explicit HeapGraphSerializer(InspectorFrontend::Memory*);
     ~HeapGraphSerializer();
     void reportNode(const WTF::MemoryObjectInfo&);
     void reportEdge(const void*, const char*, WTF::MemberType);
     void reportLeaf(const WTF::MemoryObjectInfo&, const char*);
     void reportBaseAddress(const void*, const void*);
 
-    PassRefPtr<InspectorObject> serialize();
+    void finish();
 
     void reportMemoryUsage(MemoryObjectInfo*) const;
 
 private:
+    void pushUpdateIfNeeded();
+    void pushUpdate();
+
+    int toNodeId(const void*);
+
     int addString(const String&);
     void addRootNode();
-    void adjutEdgeTargets();
 
+    void reportEdgeImpl(const int toNodeId, const char* name, int memberType);
+    int reportNodeImpl(const WTF::MemoryObjectInfo&, int edgesCount);
+
+    InspectorFrontend::Memory* m_frontend;
+
     typedef HashMap<String, int> StringMap;
     StringMap m_stringToIndex;
-    Vector<String> m_strings;
-    int m_lastReportedEdgeIndex;
+    typedef TypeBuilder::Array<String> Strings;
+    RefPtr<Strings> m_strings;
 
-    typedef HashMap<const void*, int> ObjectToNodeIndex;
-    ObjectToNodeIndex m_objectToNodeIndex;
+    typedef TypeBuilder::Array<int> Edges;
+    RefPtr<Edges> m_edges;
+    int m_nodeEdgesCount;
+    static const size_t s_edgeFieldsCount = 3;
 
-    typedef HashMap<const void*, const void*> BaseToRealAddress;
-    BaseToRealAddress m_baseToRealAddress;
+    typedef TypeBuilder::Array<int> Nodes;
+    RefPtr<Nodes> m_nodes;
+    static const size_t s_nodeFieldsCount = 5;
 
-    Vector<HeapGraphNode> m_nodes;
-    Vector<HeapGraphEdge> m_edges;
+    typedef TypeBuilder::Array<int> BaseToRealNodeIdMap;
+    RefPtr<BaseToRealNodeIdMap> m_baseToRealNodeIdMap;
+    static const size_t s_idMapEntryFieldCount = 2;
+
+    typedef HashMap<const void*, int> Address2NodeId;
+    Address2NodeId m_address2NodeIdMap;
+
     Vector<const void*> m_roots;
 
     size_t m_edgeTypes[WTF::LastMemberTypeEntry];

Modified: trunk/Source/WebCore/inspector/Inspector.json (142073 => 142074)


--- trunk/Source/WebCore/inspector/Inspector.json	2013-02-07 08:34:11 UTC (rev 142073)
+++ trunk/Source/WebCore/inspector/Inspector.json	2013-02-07 08:38:04 UTC (rev 142074)
@@ -89,6 +89,16 @@
                     { "name": "name", "type": "string", "description": "Unique name used to identify the component that allocated this block" },
                     { "name": "children", "type": "array", "optional": true, "items": { "$ref": "MemoryBlock" }}
                 ]
+            },
+            {
+                "id": "HeapSnapshotChunk",
+                "type": "object",
+                "properties": [
+                    { "name": "strings", "type": "array", "items": { "type": "string" }, "description": "An array of strings that were found since last update." },
+                    { "name": "nodes", "type": "array", "items": { "type": "integer" }, "description": "An array of nodes that were found since last update." },
+                    { "name": "edges", "type": "array", "items": { "type": "integer" }, "description": "An array of edges that were found since last update." },
+                    { "name": "baseToRealNodeId", "type": "array", "items": { "type": "integer" }, "description": "An array of integers for nodeId remapping. Even nodeId has to be mapped to the following odd nodeId." }
+                ]
             }
         ],
         "commands": [
@@ -113,10 +123,17 @@
                     { "name": "reportGraph", "type": "boolean", "optional": true, "description": "Whether native memory graph should be reported in addition to aggregated statistics." }
                 ],
                 "returns": [
-                    { "name": "distribution", "$ref": "MemoryBlock", "description": "An object describing all memory allocated by the process"},
-                    { "name": "graph", "type": "object", "optional": true, "description": "Native memory graph."}
+                    { "name": "distribution", "$ref": "MemoryBlock", "description": "An object describing all memory allocated by the process"}
                 ]
             }
+        ],
+        "events": [
+            {
+                "name": "addNativeSnapshotChunk",
+                "parameters": [
+                    { "name": "chunk", "$ref": "HeapSnapshotChunk", "description": "A chunk of the serialized the snapshot." }
+                ]
+            }
         ]
     },
     {

Modified: trunk/Source/WebCore/inspector/InspectorController.cpp (142073 => 142074)


--- trunk/Source/WebCore/inspector/InspectorController.cpp	2013-02-07 08:34:11 UTC (rev 142073)
+++ trunk/Source/WebCore/inspector/InspectorController.cpp	2013-02-07 08:38:04 UTC (rev 142074)
@@ -445,8 +445,7 @@
 HashMap<String, size_t> InspectorController::processMemoryDistribution() const
 {
     HashMap<String, size_t> memoryInfo;
-    RefPtr<InspectorObject> graph;
-    m_memoryAgent->getProcessMemoryDistributionAsMap(false, graph, &memoryInfo);
+    m_memoryAgent->getProcessMemoryDistributionMap(&memoryInfo);
     return memoryInfo;
 }
 

Modified: trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp (142073 => 142074)


--- trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp	2013-02-07 08:34:11 UTC (rev 142073)
+++ trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp	2013-02-07 08:38:04 UTC (rev 142074)
@@ -534,10 +534,15 @@
     }
 }
 
-void InspectorMemoryAgent::getProcessMemoryDistribution(ErrorString*, const bool* reportGraph, RefPtr<InspectorMemoryBlock>& processMemory, RefPtr<InspectorObject>& graph)
+void InspectorMemoryAgent::getProcessMemoryDistributionMap(TypeNameToSizeMap* memoryInfo)
 {
+    getProcessMemoryDistributionImpl(false, memoryInfo);
+}
+
+void InspectorMemoryAgent::getProcessMemoryDistribution(ErrorString*, const bool* reportGraph, RefPtr<InspectorMemoryBlock>& processMemory)
+{
     TypeNameToSizeMap memoryInfo;
-    getProcessMemoryDistributionAsMap(reportGraph && *reportGraph, graph, &memoryInfo);
+    getProcessMemoryDistributionImpl(reportGraph && *reportGraph, &memoryInfo);
 
     MemoryUsageStatsGenerator statsGenerator;
     RefPtr<InspectorMemoryBlocks> children = InspectorMemoryBlocks::create();
@@ -560,11 +565,11 @@
     info.addMember(m_page, "page");
 }
 
-void InspectorMemoryAgent::getProcessMemoryDistributionAsMap(bool reportGraph, RefPtr<InspectorObject>& graph, TypeNameToSizeMap* memoryInfo)
+void InspectorMemoryAgent::getProcessMemoryDistributionImpl(bool reportGraph, TypeNameToSizeMap* memoryInfo)
 {
     OwnPtr<HeapGraphSerializer> graphSerializer;
     if (reportGraph)
-        graphSerializer = adoptPtr(new HeapGraphSerializer());
+        graphSerializer = adoptPtr(new HeapGraphSerializer(m_frontend));
     MemoryInstrumentationClientImpl memoryInstrumentationClient(graphSerializer.get());
     m_inspectorClient->getAllocatedObjects(memoryInstrumentationClient.allocatedObjects());
     MemoryInstrumentationImpl memoryInstrumentation(&memoryInstrumentationClient);
@@ -581,7 +586,7 @@
     memoryInstrumentation.addRootObject(memoryInstrumentationClient);
     if (graphSerializer) {
         memoryInstrumentation.addRootObject(graphSerializer.get());
-        graph = graphSerializer->serialize();
+        graphSerializer->finish();
     }
 
     m_inspectorClient->dumpUncountedAllocatedObjects(memoryInstrumentationClient.countedObjects());
@@ -598,6 +603,17 @@
 {
 }
 
+void InspectorMemoryAgent::setFrontend(InspectorFrontend* frontend)
+{
+    ASSERT(!m_frontend);
+    m_frontend = frontend->memory();
+}
+
+void InspectorMemoryAgent::clearFrontend()
+{
+    m_frontend = 0;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INSPECTOR)

Modified: trunk/Source/WebCore/inspector/InspectorMemoryAgent.h (142073 => 142074)


--- trunk/Source/WebCore/inspector/InspectorMemoryAgent.h	2013-02-07 08:34:11 UTC (rev 142073)
+++ trunk/Source/WebCore/inspector/InspectorMemoryAgent.h	2013-02-07 08:38:04 UTC (rev 142074)
@@ -34,6 +34,7 @@
 #if ENABLE(INSPECTOR)
 
 #include "InspectorBaseAgent.h"
+#include "InspectorFrontend.h"
 #include <wtf/PassOwnPtr.h>
 #include <wtf/RefPtr.h>
 
@@ -60,17 +61,23 @@
 
     virtual void getDOMNodeCount(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Memory::DOMGroup> >& domGroups, RefPtr<TypeBuilder::Memory::StringStatistics>& strings);
     virtual void getDOMCounters(ErrorString*, int* documents, int* nodes, int* jsEventListeners);
-    virtual void getProcessMemoryDistribution(ErrorString*, const bool* reportGraph, RefPtr<TypeBuilder::Memory::MemoryBlock>& processMemory, RefPtr<InspectorObject>& graph);
+    virtual void getProcessMemoryDistribution(ErrorString*, const bool* reportGraph, RefPtr<TypeBuilder::Memory::MemoryBlock>& processMemory);
 
     virtual void reportMemoryUsage(MemoryObjectInfo*) const;
 
-    void getProcessMemoryDistributionAsMap(bool reportGraph, RefPtr<InspectorObject>& graph, HashMap<String, size_t>* memoryInfo);
+    void getProcessMemoryDistributionMap(HashMap<String, size_t>* memoryInfo);
 
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+
 private:
     InspectorMemoryAgent(InstrumentingAgents*, InspectorClient*, InspectorCompositeState*, Page*);
 
+    void getProcessMemoryDistributionImpl(bool reportGraph, HashMap<String, size_t>* memoryInfo);
+
     InspectorClient* m_inspectorClient;
     Page* m_page;
+    InspectorFrontend::Memory* m_frontend;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/inspector/front-end/NativeHeapSnapshot.js (142073 => 142074)


--- trunk/Source/WebCore/inspector/front-end/NativeHeapSnapshot.js	2013-02-07 08:34:11 UTC (rev 142073)
+++ trunk/Source/WebCore/inspector/front-end/NativeHeapSnapshot.js	2013-02-07 08:38:04 UTC (rev 142074)
@@ -35,6 +35,7 @@
 WebInspector.NativeHeapSnapshot = function(profile)
 {
     WebInspector.HeapSnapshot.call(this, profile);
+    this._nodeObjectType = 3;
 }
 
 WebInspector.NativeHeapSnapshot.prototype = {
@@ -88,21 +89,32 @@
 
     classIndex: function()
     {
-        var snapshot = this._snapshot;
-        return snapshot._nodes[this.nodeIndex + snapshot._nodeNameOffset];
+        return this._snapshot._nodes[this.nodeIndex + this._snapshot._nodeTypeOffset];
     },
 
     id: function()
     {
-        return this.nodeIndex;
+        return this._snapshot._nodes[this.nodeIndex + this._snapshot._nodeIdOffset];
     },
 
     name: function()
     {
-        var name = this._snapshot._strings[this._snapshot._nodes[this.nodeIndex + 2]];
-        return this.className() + ": " + name;
+        return this._snapshot._strings[this._snapshot._nodes[this.nodeIndex + this._snapshot._nodeNameOffset]];;
     },
 
+    serialize: function()
+    {
+        return {
+            id: this.id(),
+            name: this.className(),
+            distance: this.distance(),
+            nodeIndex: this.nodeIndex,
+            retainedSize: this.retainedSize(),
+            selfSize: this.selfSize(),
+            type: this._snapshot._nodeObjectType
+       };
+    },
+
     isHidden: function()
     {
         return false;

Modified: trunk/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js (142073 => 142074)


--- trunk/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js	2013-02-07 08:34:11 UTC (rev 142073)
+++ trunk/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js	2013-02-07 08:38:04 UTC (rev 142074)
@@ -264,18 +264,102 @@
         ++this._nextProfileUid;
         profileHeader.isTemporary = true;
         profilesPanel.addProfileHeader(profileHeader);
+        profileHeader.load(function() { });
+
         /**
          * @param {?string} error
          * @param {?MemoryAgent.MemoryBlock} memoryBlock
-         * @param {?Object=} graph
          */
-        function didReceiveMemorySnapshot(error, memoryBlock, graph)
+        function didReceiveMemorySnapshot(error, memoryBlock)
         {
-            profileHeader._graph = graph;
-            profileHeader.isTemporary = false;
-            profileHeader.sidebarElement.subtitle = Number.bytesToString(/** @type{number} */(memoryBlock.size));
+            this.isTemporary = false;
+            this.sidebarElement.subtitle = Number.bytesToString(/** @type{number} */(memoryBlock.size));
+
+            var meta = {
+              "node_fields": [
+                "type",
+                "name",
+                "id",
+                "self_size",
+                "edge_count"
+              ],
+              "node_types": [
+                [
+                  "hidden",
+                  "array",
+                  "string",
+                  "object",
+                  "code",
+                  "closure",
+                  "regexp",
+                  "number",
+                  "native",
+                  "synthetic"
+                ],
+                "string",
+                "number",
+                "number",
+                "number",
+              ],
+              "edge_fields": [
+                "type",
+                "name_or_index",
+                "to_node"
+              ],
+              "edge_types": [
+                [
+                  "context",
+                  "element",
+                  "property",
+                  "internal",
+                  "hidden",
+                  "shortcut",
+                  "weak"
+                ],
+                "string_or_number",
+                "node"
+              ]
+            };
+
+            var edgeFieldCount = meta.edge_fields.length;
+            var nodeFieldCount = meta.node_fields.length;
+            var nodeIdFieldOffset = meta.node_fields.indexOf("id");
+            var toNodeIdFieldOffset = meta.edge_fields.indexOf("to_node");
+
+            var baseToRealNodeIdMap = {};
+            for (var i = 0; i < this._baseToRealNodeId.length; i += 2)
+                baseToRealNodeIdMap[this._baseToRealNodeId[i]] = this._baseToRealNodeId[i + 1];
+
+            var nodeId2NodeIndex = {};
+            for (var i = nodeIdFieldOffset; i < this._nodes.length; i += nodeFieldCount)
+                nodeId2NodeIndex[this._nodes[i]] = i - nodeIdFieldOffset;
+
+            // Translate nodeId to nodeIndex.
+            var edges = this._edges;
+            for (var i = toNodeIdFieldOffset; i < edges.length; i += edgeFieldCount) {
+                if (edges[i] in baseToRealNodeIdMap)
+                    edges[i] = baseToRealNodeIdMap[edges[i]];
+                edges[i] = nodeId2NodeIndex[edges[i]];
+            }
+
+            var heapSnapshot = {
+                "snapshot": {
+                    "meta": meta,
+                    node_count: this._nodes.length / nodeFieldCount,
+                    edge_count: this._edges.length / edgeFieldCount,
+                    root_index: this._nodes.length - nodeFieldCount
+                },
+                nodes: this._nodes,
+                edges: this._edges,
+                strings: this._strings
+            };
+
+            var chunk = JSON.stringify(heapSnapshot);
+            this.transferChunk(chunk);
+            this.finishHeapSnapshot();
         }
-        MemoryAgent.getProcessMemoryDistribution(true, didReceiveMemorySnapshot.bind(this));
+
+        MemoryAgent.getProcessMemoryDistribution(true, didReceiveMemorySnapshot.bind(profileHeader));
         return false;
     },
 
@@ -324,6 +408,10 @@
 WebInspector.NativeSnapshotProfileHeader = function(type, title, uid)
 {
     WebInspector.HeapProfileHeader.call(this, type, title, uid, 0);
+    this._strings = [];
+    this._nodes = [];
+    this._edges = [];
+    this._baseToRealNodeId = [];
 }
 
 WebInspector.NativeSnapshotProfileHeader.prototype = {
@@ -338,69 +426,6 @@
 
     startSnapshotTransfer: function()
     {
-        var meta = {
-          "node_fields": [
-            "type",
-            "name",
-            "id",
-            "self_size",
-            "edge_count"
-          ],
-          "node_types": [
-            [
-              "hidden",
-              "array",
-              "string",
-              "object",
-              "code",
-              "closure",
-              "regexp",
-              "number",
-              "native",
-              "synthetic"
-            ],
-            "string",
-            "number",
-            "number",
-            "number",
-            "number",
-            "number"
-          ],
-          "edge_fields": [
-            "type",
-            "name_or_index",
-            "to_node"
-          ],
-          "edge_types": [
-            [
-              "context",
-              "element",
-              "property",
-              "internal",
-              "hidden",
-              "shortcut",
-              "weak"
-            ],
-            "string_or_number",
-            "node"
-          ]
-        };
-        var graph = this._graph;
-        var heapSnapshot = {
-            "snapshot": {
-                "meta": meta,
-                node_count: graph.nodes.length / 5,
-                edge_count: graph.edges.length / 3,
-                root_index: graph.nodes.length - 5
-            },
-            nodes: graph.nodes,
-            edges: graph.edges,
-            strings: graph.strings
-        };
-
-        var chunk = JSON.stringify(heapSnapshot);
-        this.transferChunk(chunk);
-        this.finishHeapSnapshot();
     },
 
     snapshotConstructorName: function()
@@ -408,6 +433,14 @@
         return "NativeHeapSnapshot";
     },
 
+    addNativeSnapshotChunk: function(chunk)
+    {
+        this._strings = this._strings.concat(chunk.strings);
+        this._nodes = this._nodes.concat(chunk.nodes);
+        this._edges = this._edges.concat(chunk.edges);
+        this._baseToRealNodeId = this._baseToRealNodeId.concat(chunk.baseToRealNodeId);
+    },
+
     __proto__: WebInspector.HeapProfileHeader.prototype
 }
 
@@ -467,7 +500,7 @@
          * @param {?MemoryAgent.MemoryBlock} memoryBlock
          * @param {?Object=} graph
          */
-        function didReceiveMemorySnapshot(error, memoryBlock, graph)
+        function didReceiveMemorySnapshot(error, memoryBlock)
         {
             if (memoryBlock.size && memoryBlock.children) {
                 var knownSize = 0;
@@ -645,7 +678,7 @@
          * @param {?MemoryAgent.MemoryBlock} memoryBlock
          * @param {?Object=} graph
          */
-        function didReceiveMemorySnapshot(error, memoryBlock, graph)
+        function didReceiveMemorySnapshot(error, memoryBlock)
         {
             if (memoryBlock.size && memoryBlock.children) {
                 var knownSize = 0;

Modified: trunk/Source/WebCore/inspector/front-end/ProfilesPanel.js (142073 => 142074)


--- trunk/Source/WebCore/inspector/front-end/ProfilesPanel.js	2013-02-07 08:34:11 UTC (rev 142073)
+++ trunk/Source/WebCore/inspector/front-end/ProfilesPanel.js	2013-02-07 08:38:04 UTC (rev 142074)
@@ -306,6 +306,7 @@
         this._registerProfileType(new WebInspector.CanvasProfileType());
 
     InspectorBackend.registerProfilerDispatcher(new WebInspector.ProfilerDispatcher(this));
+    InspectorBackend.registerMemoryDispatcher(new WebInspector.MemoryDispatcher(this));
 
     this._createFileSelectorElement();
     this.element.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
@@ -1226,6 +1227,32 @@
 
 /**
  * @constructor
+ * @implements {MemoryAgent.Dispatcher}
+ * @param {WebInspector.ProfilesPanel} profilesPanel
+ */
+WebInspector.MemoryDispatcher = function(profilesPanel)
+{
+    this._profilesPanel = profilesPanel;
+}
+
+WebInspector.MemoryDispatcher.prototype = {
+
+    /**
+     * @override
+     * @param {number} uid
+     * @param {string} chunk
+     */
+    addNativeSnapshotChunk: function(chunk)
+    {
+        var profile = ""
+        if (!profile)
+            return;
+        profile.addNativeSnapshotChunk(chunk);
+    }
+}
+
+/**
+ * @constructor
  * @implements {ProfilerAgent.Dispatcher}
  * @param {WebInspector.ProfilesPanel} profilesPanel
  */
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to