Title: [105157] trunk/Source/WebCore
Revision
105157
Author
[email protected]
Date
2012-01-17 07:37:06 -0800 (Tue, 17 Jan 2012)

Log Message

Web Inspector: provide basic information about DOM character data size
https://bugs.webkit.org/show_bug.cgi?id=76059

Memory agent allows to estimate size of DOM character data and size of WebCore
strings held by _javascript_ objects.

Reviewed by Pavel Feldman.

* bindings/js/ScriptProfiler.h:
(WebCore::ScriptProfiler::visitExternalJSStrings):
* bindings/v8/ScriptProfiler.cpp:
(WebCore::ScriptProfiler::visitExternalJSStrings):
* bindings/v8/ScriptProfiler.h:
* bindings/v8/V8Binding.cpp:
(WebCore::WebCoreStringResource::visitStrings):
(WebCore::V8BindingPerIsolateData::visitJSExternalStrings):
* bindings/v8/V8Binding.h:
* inspector/DOMWrapperVisitor.h:
* inspector/Inspector.json:
* inspector/InspectorMemoryAgent.cpp:
(WebCore::CharacterDataStatistics::DOMTreeStatistics::DOMTreeStatistics):
(WebCore::CharacterDataStatistics::DOMTreeStatistics::collectNodeStatistics):
(WebCore::CharacterDataStatistics::CounterVisitor::CounterVisitor):
(WebCore::CharacterDataStatistics::CounterVisitor::domGroups):
(WebCore::CharacterDataStatistics::CounterVisitor::strings):
(WebCore::CharacterDataStatistics::CounterVisitor::visitNode):
(WebCore::CharacterDataStatistics::CounterVisitor::visitJSExternalString):
(WebCore::InspectorMemoryAgent::getDOMNodeCount):
* inspector/InspectorMemoryAgent.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (105156 => 105157)


--- trunk/Source/WebCore/ChangeLog	2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/ChangeLog	2012-01-17 15:37:06 UTC (rev 105157)
@@ -1,3 +1,35 @@
+2012-01-11  Yury Semikhatsky  <[email protected]>
+
+        Web Inspector: provide basic information about DOM character data size
+        https://bugs.webkit.org/show_bug.cgi?id=76059
+
+        Memory agent allows to estimate size of DOM character data and size of WebCore
+        strings held by _javascript_ objects.
+
+        Reviewed by Pavel Feldman.
+
+        * bindings/js/ScriptProfiler.h:
+        (WebCore::ScriptProfiler::visitExternalJSStrings):
+        * bindings/v8/ScriptProfiler.cpp:
+        (WebCore::ScriptProfiler::visitExternalJSStrings):
+        * bindings/v8/ScriptProfiler.h:
+        * bindings/v8/V8Binding.cpp:
+        (WebCore::WebCoreStringResource::visitStrings):
+        (WebCore::V8BindingPerIsolateData::visitJSExternalStrings):
+        * bindings/v8/V8Binding.h:
+        * inspector/DOMWrapperVisitor.h:
+        * inspector/Inspector.json:
+        * inspector/InspectorMemoryAgent.cpp:
+        (WebCore::CharacterDataStatistics::DOMTreeStatistics::DOMTreeStatistics):
+        (WebCore::CharacterDataStatistics::DOMTreeStatistics::collectNodeStatistics):
+        (WebCore::CharacterDataStatistics::CounterVisitor::CounterVisitor):
+        (WebCore::CharacterDataStatistics::CounterVisitor::domGroups):
+        (WebCore::CharacterDataStatistics::CounterVisitor::strings):
+        (WebCore::CharacterDataStatistics::CounterVisitor::visitNode):
+        (WebCore::CharacterDataStatistics::CounterVisitor::visitJSExternalString):
+        (WebCore::InspectorMemoryAgent::getDOMNodeCount):
+        * inspector/InspectorMemoryAgent.h:
+
 2012-01-17  Vsevolod Vlasov  <[email protected]>
 
         Web Inspector: Dialogs style and DialogDelegate interface fixes.

Modified: trunk/Source/WebCore/bindings/js/ScriptProfiler.h (105156 => 105157)


--- trunk/Source/WebCore/bindings/js/ScriptProfiler.h	2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/bindings/js/ScriptProfiler.h	2012-01-17 15:37:06 UTC (rev 105157)
@@ -62,6 +62,7 @@
     static bool hasHeapProfiler() { return false; }
     // FIXME: Implement this counter for JSC. See bug 73936 for more details.
     static void visitJSDOMWrappers(DOMWrapperVisitor*) { }
+    static void visitExternalJSStrings(DOMWrapperVisitor*) { }
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp (105156 => 105157)


--- trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp	2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp	2012-01-17 15:37:06 UTC (rev 105157)
@@ -159,4 +159,9 @@
     visitDOMNodes(&adapter);
 }
 
+void ScriptProfiler::visitExternalJSStrings(DOMWrapperVisitor* visitor)
+{
+    V8BindingPerIsolateData::current()->visitJSExternalStrings(visitor);
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/v8/ScriptProfiler.h (105156 => 105157)


--- trunk/Source/WebCore/bindings/v8/ScriptProfiler.h	2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/bindings/v8/ScriptProfiler.h	2012-01-17 15:37:06 UTC (rev 105157)
@@ -66,6 +66,7 @@
     static bool hasHeapProfiler() { return true; }
     static void initialize();
     static void visitJSDOMWrappers(DOMWrapperVisitor*);
+    static void visitExternalJSStrings(DOMWrapperVisitor*);
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/v8/V8Binding.cpp (105156 => 105157)


--- trunk/Source/WebCore/bindings/v8/V8Binding.cpp	2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/bindings/v8/V8Binding.cpp	2012-01-17 15:37:06 UTC (rev 105157)
@@ -32,6 +32,7 @@
 #include "V8Binding.h"
 
 #include "DOMStringList.h"
+#include "DOMWrapperVisitor.h"
 #include "Element.h"
 #include "MathExtras.h"
 #include "PlatformString.h"
@@ -145,6 +146,13 @@
         return m_atomicString;
     }
 
+    void visitStrings(DOMWrapperVisitor* visitor)
+    {
+        visitor->visitJSExternalString(m_plainString.impl());
+        if (m_plainString.impl() != m_atomicString.impl() && !m_atomicString.isNull())
+            visitor->visitJSExternalString(m_atomicString.impl());
+    }
+
     static WebCoreStringResource* toStringResource(v8::Handle<v8::String> v8String)
     {
         return static_cast<WebCoreStringResource*>(v8String->GetExternalStringResource());
@@ -165,6 +173,25 @@
 #endif
 };
 
+void V8BindingPerIsolateData::visitJSExternalStrings(DOMWrapperVisitor* visitor)
+{
+    v8::HandleScope handleScope;
+    class VisitorImpl : public v8::ExternalResourceVisitor {
+    public:
+        VisitorImpl(DOMWrapperVisitor* visitor) : m_visitor(visitor) { }
+        virtual ~VisitorImpl() { }
+        virtual void VisitExternalString(v8::Handle<v8::String> string)
+        {
+            WebCoreStringResource* resource = static_cast<WebCoreStringResource*>(string->GetExternalStringResource());
+            if (resource)
+                resource->visitStrings(m_visitor);
+        }
+    private:
+        DOMWrapperVisitor* m_visitor;
+    } v8Visitor(visitor);
+    v8::V8::VisitExternalResources(&v8Visitor);
+}
+
 String v8ValueToWebCoreString(v8::Handle<v8::Value> value)
 {
     if (value->IsString())
@@ -502,7 +529,6 @@
     m_stringCache.remove(stringImpl);
 }
 
-
 v8::Local<v8::String> StringCache::v8ExternalStringSlow(StringImpl* stringImpl)
 {
     if (!stringImpl->length())

Modified: trunk/Source/WebCore/bindings/v8/V8Binding.h (105156 => 105157)


--- trunk/Source/WebCore/bindings/v8/V8Binding.h	2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/bindings/v8/V8Binding.h	2012-01-17 15:37:06 UTC (rev 105157)
@@ -46,6 +46,7 @@
 namespace WebCore {
 
     class DOMStringList;
+    class DOMWrapperVisitor;
     class EventListener;
     class EventTarget;
 
@@ -123,6 +124,7 @@
         }
 
         StringCache* stringCache() { return &m_stringCache; }
+        void visitJSExternalStrings(DOMWrapperVisitor*);
 
         DOMDataList& allStores() { return m_domDataList; }
 

Modified: trunk/Source/WebCore/inspector/DOMWrapperVisitor.h (105156 => 105157)


--- trunk/Source/WebCore/inspector/DOMWrapperVisitor.h	2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/inspector/DOMWrapperVisitor.h	2012-01-17 15:37:06 UTC (rev 105157)
@@ -36,6 +36,7 @@
 class DOMWrapperVisitor {
 public:
     virtual void visitNode(Node*) = 0;
+    virtual void visitJSExternalString(StringImpl*) = 0;
 protected:
     virtual ~DOMWrapperVisitor() { }
 };

Modified: trunk/Source/WebCore/inspector/Inspector.json (105156 => 105157)


--- trunk/Source/WebCore/inspector/Inspector.json	2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/inspector/Inspector.json	2012-01-17 15:37:06 UTC (rev 105157)
@@ -68,6 +68,16 @@
                 "description": "Number of JS event listeners by event type."
             },
             {
+                "id": "StringStatistics",
+                "type": "object",
+                "properties": [
+                    { "name": "dom", "type": "integer" },
+                    { "name": "js", "type": "integer" },
+                    { "name": "shared", "type": "integer" }
+                ],
+                "description": "Character data statistics for the page."
+            },
+            {
                 "id": "DOMGroup",
                 "type": "object",
                 "properties": [
@@ -83,7 +93,8 @@
             {
                 "name": "getDOMNodeCount",
                 "returns": [
-                    { "name": "count", "type": "array", "items": { "$ref": "DOMGroup" }}
+                    { "name": "domGroups", "type": "array", "items": { "$ref": "DOMGroup" }},
+                    { "name": "strings", "$ref": "StringStatistics" }
                 ]
             }
         ]

Modified: trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp (105156 => 105157)


--- trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp	2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp	2012-01-17 15:37:06 UTC (rev 105157)
@@ -33,6 +33,7 @@
 
 #if ENABLE(INSPECTOR)
 
+#include "CharacterData.h"
 #include "DOMWrapperVisitor.h"
 #include "Document.h"
 #include "EventListenerMap.h"
@@ -51,6 +52,7 @@
 using WebCore::TypeBuilder::Memory::DOMGroup;
 using WebCore::TypeBuilder::Memory::ListenerCount;
 using WebCore::TypeBuilder::Memory::NodeCount;
+using WebCore::TypeBuilder::Memory::StringStatistics;
 
 namespace WebCore {
 
@@ -63,11 +65,50 @@
     return node->nodeName().lower();
 }
 
+int stringSize(StringImpl* string)
+{
+    int size = string->length();
+    if (!string->is8Bit())
+        size *= 2;
+    return size + sizeof(*string);
+}
+
 typedef HashSet<StringImpl*, PtrHash<StringImpl*> > StringImplIdentitySet;
 
+class CharacterDataStatistics {
+    WTF_MAKE_NONCOPYABLE(CharacterDataStatistics);
+public:
+    CharacterDataStatistics() : m_characterDataSize(0) { }
+
+    void collectCharacterData(Node* node)
+    {
+        if (!node->isCharacterDataNode())
+            return;
+
+        CharacterData* characterData = static_cast<CharacterData*>(node);
+        StringImpl* dataImpl = characterData->dataImpl();
+        if (m_domStringImplSet.contains(dataImpl))
+            return;
+        m_domStringImplSet.add(dataImpl);
+
+        m_characterDataSize += stringSize(dataImpl);
+    }
+
+    bool contains(StringImpl* s) { return m_domStringImplSet.contains(s); }
+
+    int characterDataSize() { return m_characterDataSize; }
+
+private:
+    StringImplIdentitySet m_domStringImplSet;
+    int m_characterDataSize;
+};
+
 class DOMTreeStatistics {
+    WTF_MAKE_NONCOPYABLE(DOMTreeStatistics);
 public:
-    DOMTreeStatistics(Node* rootNode) : m_totalNodeCount(0)
+    DOMTreeStatistics(Node* rootNode, CharacterDataStatistics& characterDataStatistics)
+        : m_totalNodeCount(0)
+        , m_characterDataStatistics(characterDataStatistics)
     {
         collectTreeStatistics(rootNode);
     }
@@ -108,7 +149,7 @@
     }
     void collectNodeStatistics(Node* node)
     {
-        collectCharacterData(node);
+        m_characterDataStatistics.collectCharacterData(node);
         collectNodeNameInfo(node);
         collectListenersInfo(node);
     }
@@ -149,15 +190,28 @@
     int m_totalNodeCount;
     HashMap<AtomicString, int> m_eventTypeToCount;
     HashMap<String, int> m_nodeNameToCount;
-    StringImplIdentitySet m_domStringImplSet;
+    CharacterDataStatistics& m_characterDataStatistics;
 };
 
 class CounterVisitor : public DOMWrapperVisitor {
 public:
-    CounterVisitor(Page* page) : m_page(page), m_counters(InspectorArray::create()) { }
+    CounterVisitor(Page* page)
+        : m_page(page)
+        , m_domGroups(InspectorArray::create())
+        , m_jsExternalStringSize(0)
+        , m_sharedStringSize(0) { }
 
-    InspectorArray* counters() { return m_counters.get(); }
+    InspectorArray* domGroups() { return m_domGroups.get(); }
 
+    PassRefPtr<InspectorObject> strings()
+    {
+        RefPtr<StringStatistics> stringStatistics = StringStatistics::create()
+            .setDom(m_characterDataStatistics.characterDataSize())
+            .setJs(m_jsExternalStringSize)
+            .setShared(m_sharedStringSize);
+        return stringStatistics.release();
+    }
+
     virtual void visitNode(Node* node)
     {
         if (node->document()->frame() && m_page != node->document()->frame()->page())
@@ -171,7 +225,7 @@
             return;
         m_roots.add(rootNode);
 
-        DOMTreeStatistics domTreeStats(rootNode);
+        DOMTreeStatistics domTreeStats(rootNode, m_characterDataStatistics);
 
         RefPtr<DOMGroup> domGroup = DOMGroup::create()
             .setSize(domTreeStats.totalNodeCount())
@@ -181,9 +235,17 @@
         if (rootNode->nodeType() == Node::DOCUMENT_NODE)
             domGroup->setDocumentURI(static_cast<Document*>(rootNode)->documentURI());
 
-        m_counters->pushObject(domGroup);
+        m_domGroups->pushObject(domGroup);
     }
 
+    virtual void visitJSExternalString(StringImpl* string)
+    {
+        int size = stringSize(string);
+        m_jsExternalStringSize += size;
+        if (m_characterDataStatistics.contains(string))
+            m_sharedStringSize += size;
+    }
+
 private:
     String elementTitle(Element* element)
     {
@@ -215,7 +277,10 @@
 
     HashSet<Node*> m_roots;
     Page* m_page;
-    RefPtr<InspectorArray> m_counters;
+    RefPtr<InspectorArray> m_domGroups;
+    CharacterDataStatistics m_characterDataStatistics;
+    int m_jsExternalStringSize;
+    int m_sharedStringSize;
 };
 
 } // namespace
@@ -224,7 +289,7 @@
 {
 }
 
-void InspectorMemoryAgent::getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>& result)
+void InspectorMemoryAgent::getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>& domGroups, RefPtr<InspectorObject>& strings)
 {
     CounterVisitor counterVisitor(m_page);
     ScriptProfiler::visitJSDOMWrappers(&counterVisitor);
@@ -235,7 +300,10 @@
             counterVisitor.visitNode(doc);
     }
 
-    result = counterVisitor.counters();
+    ScriptProfiler::visitExternalJSStrings(&counterVisitor);
+
+    domGroups = counterVisitor.domGroups();
+    strings = counterVisitor.strings();
 }
 
 InspectorMemoryAgent::InspectorMemoryAgent(InstrumentingAgents* instrumentingAgents, InspectorState* state, Page* page, InspectorDOMAgent* domAgent)

Modified: trunk/Source/WebCore/inspector/InspectorMemoryAgent.h (105156 => 105157)


--- trunk/Source/WebCore/inspector/InspectorMemoryAgent.h	2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/inspector/InspectorMemoryAgent.h	2012-01-17 15:37:06 UTC (rev 105157)
@@ -57,7 +57,7 @@
         return adoptPtr(new InspectorMemoryAgent(instrumentingAgents, state, page, domAgent));
     }
 
-    void getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>& result);
+    void getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>& domGroups, RefPtr<InspectorObject>& strings);
 
     ~InspectorMemoryAgent();
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to