summaryrefslogtreecommitdiff
path: root/Source/WebCore/inspector/InspectorMemoryAgent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/inspector/InspectorMemoryAgent.cpp')
-rw-r--r--Source/WebCore/inspector/InspectorMemoryAgent.cpp335
1 files changed, 148 insertions, 187 deletions
diff --git a/Source/WebCore/inspector/InspectorMemoryAgent.cpp b/Source/WebCore/inspector/InspectorMemoryAgent.cpp
index 2cef9ad56..badcb795b 100644
--- a/Source/WebCore/inspector/InspectorMemoryAgent.cpp
+++ b/Source/WebCore/inspector/InspectorMemoryAgent.cpp
@@ -39,6 +39,7 @@
#include "Document.h"
#include "EventListenerMap.h"
#include "Frame.h"
+#include "InspectorClient.h"
#include "InspectorDOMStorageAgent.h"
#include "InspectorFrontend.h"
#include "InspectorState.h"
@@ -52,9 +53,10 @@
#include "ScriptGCEvent.h"
#include "ScriptProfiler.h"
#include "StyledElement.h"
-#include <wtf/ArrayBuffer.h>
#include <wtf/ArrayBufferView.h>
#include <wtf/HashSet.h>
+#include <wtf/MemoryInstrumentationArrayBufferView.h>
+#include <wtf/NonCopyingSort.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
@@ -69,28 +71,88 @@ using WebCore::TypeBuilder::Memory::StringStatistics;
// Use a type alias instead of 'using' here which would cause a conflict on Mac.
typedef WebCore::TypeBuilder::Memory::MemoryBlock InspectorMemoryBlock;
+typedef WebCore::TypeBuilder::Array<InspectorMemoryBlock> InspectorMemoryBlocks;
namespace WebCore {
-namespace MemoryBlockName {
-static const char jsHeapAllocated[] = "JSHeapAllocated";
-static const char jsHeapUsed[] = "JSHeapUsed";
-static const char jsExternalResources[] = "JSExternalResources";
-static const char jsExternalArrays[] = "JSExternalArrays";
-static const char jsExternalStrings[] = "JSExternalStrings";
-static const char inspectorData[] = "InspectorData";
-static const char inspectorDOMData[] = "InspectorDOMData";
-static const char inspectorJSHeapData[] = "InspectorJSHeapData";
-static const char processPrivateMemory[] = "ProcessPrivateMemory";
-
-static const char renderTreeUsed[] = "RenderTreeUsed";
-static const char renderTreeAllocated[] = "RenderTreeAllocated";
-
-static const char domStorageCache[] = "DOMStorageCache";
-}
-
namespace {
+class MemoryUsageStatsGenerator {
+public:
+ MemoryUsageStatsGenerator(MemoryInstrumentationClientImpl* client) : m_client(client) { }
+
+ void dump(InspectorMemoryBlocks* children)
+ {
+ m_sizesMap = m_client->sizesMap();
+
+ Vector<String> objectTypes;
+ objectTypes.appendRange(m_sizesMap.keys().begin(), m_sizesMap.keys().end());
+
+ for (Vector<String>::const_iterator i = objectTypes.begin(); i != objectTypes.end(); ++i)
+ updateParentSizes(*i, m_sizesMap.get(*i));
+
+ objectTypes.clear();
+ objectTypes.appendRange(m_sizesMap.keys().begin(), m_sizesMap.keys().end());
+ nonCopyingSort(objectTypes.begin(), objectTypes.end(), stringCompare);
+
+ size_t index = 0;
+ while (index < objectTypes.size())
+ index = buildObjectForIndex(index, objectTypes, children);
+
+ addMemoryInstrumentationDebugData(children);
+ }
+
+private:
+ static bool stringCompare(const String& a, const String& b) { return WTF::codePointCompare(a, b) < 0; }
+
+ void updateParentSizes(String objectType, const size_t size)
+ {
+ for (size_t dotPosition = objectType.reverseFind('.'); dotPosition != notFound; dotPosition = objectType.reverseFind('.', dotPosition)) {
+ objectType = objectType.substring(0, dotPosition);
+ TypeNameToSizeMap::AddResult result = m_sizesMap.add(objectType, size);
+ if (!result.isNewEntry)
+ result.iterator->value += size;
+ }
+ }
+
+ size_t buildObjectForIndex(size_t index, const Vector<String>& objectTypes, InspectorMemoryBlocks* array)
+ {
+ String typeName = objectTypes[index];
+ RefPtr<InspectorMemoryBlock> block = InspectorMemoryBlock::create().setName(typeName);
+ block->setSize(m_sizesMap.get(typeName));
+ String prefix = typeName;
+ prefix.append('.');
+ array->addItem(block);
+ ++index;
+ RefPtr<InspectorMemoryBlocks> children;
+ while (index < objectTypes.size() && objectTypes[index].startsWith(prefix)) {
+ if (!children)
+ children = InspectorMemoryBlocks::create();
+ index = buildObjectForIndex(index, objectTypes, children.get());
+ }
+ if (children)
+ block->setChildren(children.release());
+ return index;
+ }
+
+ void addMemoryInstrumentationDebugData(InspectorMemoryBlocks* children)
+ {
+ if (m_client->checkInstrumentedObjects()) {
+ RefPtr<InspectorMemoryBlock> totalInstrumented = InspectorMemoryBlock::create().setName("InstrumentedObjectsCount");
+ totalInstrumented->setSize(m_client->totalCountedObjects());
+
+ RefPtr<InspectorMemoryBlock> incorrectlyInstrumented = InspectorMemoryBlock::create().setName("InstrumentedButNotAllocatedObjectsCount");
+ incorrectlyInstrumented->setSize(m_client->totalObjectsNotInAllocatedSet());
+
+ children->addItem(totalInstrumented);
+ children->addItem(incorrectlyInstrumented);
+ }
+ }
+
+ MemoryInstrumentationClientImpl* m_client;
+ TypeNameToSizeMap m_sizesMap;
+};
+
String nodeName(Node* node)
{
if (node->document()->isXHTMLDocument())
@@ -144,8 +206,8 @@ public:
{
RefPtr<TypeBuilder::Array<TypeBuilder::Memory::NodeCount> > childrenStats = TypeBuilder::Array<TypeBuilder::Memory::NodeCount>::create();
for (HashMap<String, int>::iterator it = m_nodeNameToCount.begin(); it != m_nodeNameToCount.end(); ++it) {
- RefPtr<NodeCount> nodeCount = NodeCount::create().setNodeName(it->first)
- .setCount(it->second);
+ RefPtr<NodeCount> nodeCount = NodeCount::create().setNodeName(it->key)
+ .setCount(it->value);
childrenStats->addItem(nodeCount);
}
return childrenStats.release();
@@ -155,8 +217,8 @@ public:
{
RefPtr<TypeBuilder::Array<TypeBuilder::Memory::ListenerCount> > listenerStats = TypeBuilder::Array<TypeBuilder::Memory::ListenerCount>::create();
for (HashMap<AtomicString, int>::iterator it = m_eventTypeToCount.begin(); it != m_eventTypeToCount.end(); ++it) {
- RefPtr<ListenerCount> listenerCount = ListenerCount::create().setType(it->first)
- .setCount(it->second);
+ RefPtr<ListenerCount> listenerCount = ListenerCount::create().setType(it->key)
+ .setCount(it->value);
listenerStats->addItem(listenerCount);
}
return listenerStats.release();
@@ -304,65 +366,46 @@ private:
int m_sharedStringSize;
};
-class ExternalResourceVisitor : public ExternalStringVisitor, public ExternalArrayVisitor {
+class ExternalStringsRoot : public ExternalStringVisitor {
public:
- explicit ExternalResourceVisitor(VisitedObjects& visitedObjects)
- : m_visitedObjects(visitedObjects)
- , m_jsExternalStringSize(0)
- , m_externalArraySize(0)
- { }
-
- size_t externalStringSize() const { return m_jsExternalStringSize; }
- size_t externalArraySize() const { return m_externalArraySize; }
+ ExternalStringsRoot() : m_memoryClassInfo(0) { }
-private:
- virtual void visitJSExternalArray(ArrayBufferView* bufferView)
+ void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
{
- ArrayBuffer* buffer = bufferView->buffer().get();
- if (m_visitedObjects.add(buffer).isNewEntry)
- m_externalArraySize += buffer->byteLength();
+ MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::ExternalStrings);
+ m_memoryClassInfo = &info;
+ ScriptProfiler::visitExternalStrings(const_cast<ExternalStringsRoot*>(this));
+ m_memoryClassInfo = 0;
}
+
+private:
virtual void visitJSExternalString(StringImpl* string)
{
- if (m_visitedObjects.add(string).isNewEntry)
- m_jsExternalStringSize += string->sizeInBytes();
+ m_memoryClassInfo->addMember(string);
}
- VisitedObjects& m_visitedObjects;
- size_t m_jsExternalStringSize;
- size_t m_externalArraySize;
+ mutable MemoryClassInfo* m_memoryClassInfo;
};
-class InspectorDataCounter {
+class ExternalArraysRoot : public ExternalArrayVisitor {
public:
- void addComponent(const String& name, size_t size)
- {
- m_components.append(ComponentInfo(name, size));
- }
+ ExternalArraysRoot() : m_memoryClassInfo(0) { }
- PassRefPtr<InspectorMemoryBlock> dumpStatistics()
+ void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
{
- size_t totalSize = 0;
- RefPtr<InspectorMemoryBlock> block = InspectorMemoryBlock::create().setName(MemoryBlockName::inspectorData);
- for (Vector<ComponentInfo>::iterator it = m_components.begin(); it != m_components.end(); ++it) {
- RefPtr<InspectorMemoryBlock> block = InspectorMemoryBlock::create().setName(it->m_name);
- block->setSize(it->m_size);
- totalSize += it->m_size;
- }
- block->setSize(totalSize);
- return block;
+ MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::ExternalArrays);
+ m_memoryClassInfo = &info;
+ ScriptProfiler::visitExternalArrays(const_cast<ExternalArraysRoot*>(this));
+ m_memoryClassInfo = 0;
}
private:
- class ComponentInfo {
- public:
- ComponentInfo(const String& name, size_t size) : m_name(name), m_size(size) { }
-
- const String m_name;
- size_t m_size;
- };
+ virtual void visitJSExternalArray(ArrayBufferView* arrayBufferView)
+ {
+ m_memoryClassInfo->addMember(arrayBufferView);
+ }
- Vector<ComponentInfo> m_components;
+ mutable MemoryClassInfo* m_memoryClassInfo;
};
} // namespace
@@ -388,44 +431,28 @@ void InspectorMemoryAgent::getDOMNodeCount(ErrorString*, RefPtr<TypeBuilder::Arr
strings = counterVisitor.strings();
}
-static PassRefPtr<InspectorMemoryBlock> jsHeapInfo()
+static void reportJSHeapInfo(WTF::MemoryInstrumentationClient& memoryInstrumentationClient)
{
HeapInfo info;
ScriptGCEvent::getHeapSize(info);
- RefPtr<InspectorMemoryBlock> jsHeapAllocated = InspectorMemoryBlock::create().setName(MemoryBlockName::jsHeapAllocated);
- jsHeapAllocated->setSize(static_cast<int>(info.totalJSHeapSize));
-
- RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > children = TypeBuilder::Array<InspectorMemoryBlock>::create();
- RefPtr<InspectorMemoryBlock> jsHeapUsed = InspectorMemoryBlock::create().setName(MemoryBlockName::jsHeapUsed);
- jsHeapUsed->setSize(static_cast<int>(info.usedJSHeapSize));
- children->addItem(jsHeapUsed);
-
- jsHeapAllocated->setChildren(children);
- return jsHeapAllocated.release();
+ memoryInstrumentationClient.countObjectSize(WebCoreMemoryTypes::JSHeapUsed, info.usedJSHeapSize);
+ memoryInstrumentationClient.countObjectSize(WebCoreMemoryTypes::JSHeapUnused, info.totalJSHeapSize - info.usedJSHeapSize);
}
-static PassRefPtr<InspectorMemoryBlock> renderTreeInfo(Page* page)
+static void reportRenderTreeInfo(WTF::MemoryInstrumentationClient& memoryInstrumentationClient, Page* page)
{
ArenaSize arenaSize = page->renderTreeSize();
- RefPtr<InspectorMemoryBlock> renderTreeAllocated = InspectorMemoryBlock::create().setName(MemoryBlockName::renderTreeAllocated);
- renderTreeAllocated->setSize(arenaSize.allocated);
-
- RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > children = TypeBuilder::Array<InspectorMemoryBlock>::create();
- RefPtr<InspectorMemoryBlock> renderTreeUsed = InspectorMemoryBlock::create().setName(MemoryBlockName::renderTreeUsed);
- renderTreeUsed->setSize(arenaSize.treeSize);
- children->addItem(renderTreeUsed);
-
- renderTreeAllocated->setChildren(children);
- return renderTreeAllocated.release();
+ memoryInstrumentationClient.countObjectSize(WebCoreMemoryTypes::RenderTreeUsed, arenaSize.treeSize);
+ memoryInstrumentationClient.countObjectSize(WebCoreMemoryTypes::RenderTreeUnused, arenaSize.allocated - arenaSize.treeSize);
}
namespace {
class DOMTreesIterator : public NodeWrapperVisitor {
public:
- DOMTreesIterator(Page* page, MemoryInstrumentationImpl& memoryInstrumentation)
+ DOMTreesIterator(MemoryInstrumentationImpl& memoryInstrumentation, Page* page)
: m_page(page)
, m_memoryInstrumentation(memoryInstrumentation)
{
@@ -454,72 +481,23 @@ public:
m_memoryInstrumentation.addRootObject(memoryCache());
}
- PassRefPtr<InspectorMemoryBlock> buildObjectForMemoryCache() const
- {
- size_t totalSize = 0;
-
- RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > children = TypeBuilder::Array<InspectorMemoryBlock>::create();
- totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::MemoryCacheStructures);
- totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceRaw);
- totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceCSS);
- totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceFont);
- totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceImage);
- totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceScript);
- totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceSVG);
- totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceShader);
- totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceXSLT);
-
- RefPtr<InspectorMemoryBlock> block = InspectorMemoryBlock::create().setName(WebCoreMemoryTypes::MemoryCache);
- block->setSize(totalSize);
- block->setChildren(children.release());
- return block.release();
- }
-
- PassRefPtr<InspectorMemoryBlock> buildObjectForPage() const
- {
- size_t totalSize = 0;
-
- RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > domChildren = TypeBuilder::Array<InspectorMemoryBlock>::create();
- totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::DOM);
- totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::Image);
- totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::CSS);
- totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::Binding);
- totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::Loader);
-
- RefPtr<InspectorMemoryBlock> dom = InspectorMemoryBlock::create().setName(WebCoreMemoryTypes::Page);
- dom->setSize(totalSize);
- dom->setChildren(domChildren.release());
- return dom.release();
- }
-
- void dumpStatistics(TypeBuilder::Array<InspectorMemoryBlock>* children, InspectorDataCounter* inspectorData)
- {
- children->addItem(buildObjectForMemoryCache());
- children->addItem(buildObjectForPage());
-
- inspectorData->addComponent(MemoryBlockName::inspectorDOMData, m_memoryInstrumentation.selfSize());
- }
private:
- size_t addMemoryBlockFor(TypeBuilder::Array<InspectorMemoryBlock>* array, MemoryObjectType typeName) const
- {
- RefPtr<InspectorMemoryBlock> result = InspectorMemoryBlock::create().setName(typeName);
- size_t size = m_memoryInstrumentation.totalSize(typeName);
- result->setSize(size);
- array->addItem(result);
- return size;
- }
-
Page* m_page;
MemoryInstrumentationImpl& m_memoryInstrumentation;
};
}
-static void collectDomTreeInfo(Page* page, VisitedObjects& visitedObjects, TypeBuilder::Array<InspectorMemoryBlock>* children, InspectorDataCounter* inspectorData)
+static void collectDomTreeInfo(MemoryInstrumentationImpl& memoryInstrumentation, Page* page)
{
- MemoryInstrumentationImpl memoryInstrumentation(visitedObjects);
- DOMTreesIterator domTreesIterator(page, memoryInstrumentation);
+ ExternalStringsRoot stringsRoot;
+ memoryInstrumentation.addRootObject(stringsRoot);
+
+ ExternalArraysRoot arraysRoot;
+ memoryInstrumentation.addRootObject(arraysRoot);
+
+ DOMTreesIterator domTreesIterator(memoryInstrumentation, page);
ScriptProfiler::visitNodeWrappers(&domTreesIterator);
@@ -533,11 +511,9 @@ static void collectDomTreeInfo(Page* page, VisitedObjects& visitedObjects, TypeB
domTreesIterator.visitBindings();
domTreesIterator.visitMemoryCache();
-
- domTreesIterator.dumpStatistics(children, inspectorData);
}
-static void addPlatformComponentsInfo(PassRefPtr<TypeBuilder::Array<InspectorMemoryBlock> > children)
+static void addPlatformComponentsInfo(PassRefPtr<InspectorMemoryBlocks> children)
{
Vector<MemoryUsageSupport::ComponentInfo> components;
MemoryUsageSupport::memoryUsageByComponents(components);
@@ -548,50 +524,27 @@ static void addPlatformComponentsInfo(PassRefPtr<TypeBuilder::Array<InspectorMem
}
}
-static PassRefPtr<InspectorMemoryBlock> jsExternalResourcesInfo(VisitedObjects& visitedObjects)
+void InspectorMemoryAgent::getProcessMemoryDistribution(ErrorString*, RefPtr<InspectorMemoryBlock>& processMemory)
{
- ExternalResourceVisitor visitor(visitedObjects);
- ScriptProfiler::visitExternalStrings(&visitor);
- ScriptProfiler::visitExternalArrays(&visitor);
+ MemoryInstrumentationClientImpl memoryInstrumentationClient;
+ m_inspectorClient->getAllocatedObjects(memoryInstrumentationClient.allocatedObjects());
+ MemoryInstrumentationImpl memoryInstrumentation(&memoryInstrumentationClient);
- RefPtr<InspectorMemoryBlock> externalResourcesStats = InspectorMemoryBlock::create().setName(MemoryBlockName::jsExternalResources);
- externalResourcesStats->setSize(visitor.externalStringSize() + visitor.externalArraySize());
- RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > children = TypeBuilder::Array<InspectorMemoryBlock>::create();
+ reportJSHeapInfo(memoryInstrumentationClient);
+ reportRenderTreeInfo(memoryInstrumentationClient, m_page);
+ collectDomTreeInfo(memoryInstrumentation, m_page); // FIXME: collect for all pages?
- RefPtr<InspectorMemoryBlock> externalStringStats = InspectorMemoryBlock::create().setName(MemoryBlockName::jsExternalStrings);
- externalStringStats->setSize(visitor.externalStringSize());
- children->addItem(externalStringStats);
-
- RefPtr<InspectorMemoryBlock> externalArrayStats = InspectorMemoryBlock::create().setName(MemoryBlockName::jsExternalArrays);
- externalArrayStats->setSize(visitor.externalArraySize());
- children->addItem(externalArrayStats);
+ RefPtr<InspectorMemoryBlocks> children = InspectorMemoryBlocks::create();
+ addPlatformComponentsInfo(children);
- return externalResourcesStats.release();
-}
+ memoryInstrumentation.addRootObject(this);
+ memoryInstrumentation.addRootObject(memoryInstrumentation);
+ memoryInstrumentation.addRootObject(memoryInstrumentationClient);
-static PassRefPtr<InspectorMemoryBlock> dumpDOMStorageCache(size_t cacheSize)
-{
- RefPtr<InspectorMemoryBlock> domStorageCache = InspectorMemoryBlock::create().setName(MemoryBlockName::domStorageCache);
- domStorageCache->setSize(cacheSize);
- return domStorageCache;
-}
+ MemoryUsageStatsGenerator statsGenerator(&memoryInstrumentationClient);
+ statsGenerator.dump(children.get());
-void InspectorMemoryAgent::getProcessMemoryDistribution(ErrorString*, RefPtr<InspectorMemoryBlock>& processMemory)
-{
- processMemory = InspectorMemoryBlock::create().setName(MemoryBlockName::processPrivateMemory);
-
- InspectorDataCounter inspectorData;
- inspectorData.addComponent(MemoryBlockName::inspectorJSHeapData, ScriptProfiler::profilerSnapshotsSize());
-
- VisitedObjects visitedObjects;
- RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > children = TypeBuilder::Array<InspectorMemoryBlock>::create();
- children->addItem(jsHeapInfo());
- children->addItem(renderTreeInfo(m_page)); // FIXME: collect for all pages?
- children->addItem(jsExternalResourcesInfo(visitedObjects));
- collectDomTreeInfo(m_page, visitedObjects, children.get(), &inspectorData); // FIXME: collect for all pages?
- children->addItem(inspectorData.dumpStatistics());
- children->addItem(dumpDOMStorageCache(m_domStorageAgent->memoryBytesUsedByStorageCache()));
- addPlatformComponentsInfo(children);
+ processMemory = InspectorMemoryBlock::create().setName(WebCoreMemoryTypes::ProcessPrivateMemory);
processMemory->setChildren(children);
size_t privateBytes = 0;
@@ -600,10 +553,18 @@ void InspectorMemoryAgent::getProcessMemoryDistribution(ErrorString*, RefPtr<Ins
processMemory->setSize(privateBytes);
}
-InspectorMemoryAgent::InspectorMemoryAgent(InstrumentingAgents* instrumentingAgents, InspectorState* state, Page* page, InspectorDOMStorageAgent* domStorageAgent)
+void InspectorMemoryAgent::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+ MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Inspector);
+ InspectorBaseAgent<InspectorMemoryAgent>::reportMemoryUsage(memoryObjectInfo);
+ info.addMember(m_inspectorClient);
+ info.addMember(m_page);
+}
+
+InspectorMemoryAgent::InspectorMemoryAgent(InstrumentingAgents* instrumentingAgents, InspectorClient* client, InspectorState* state, Page* page)
: InspectorBaseAgent<InspectorMemoryAgent>("Memory", instrumentingAgents, state)
+ , m_inspectorClient(client)
, m_page(page)
- , m_domStorageAgent(domStorageAgent)
{
}