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
*/