+2012-01-11 Yury Semikhatsky <yurys@chromium.org>
+
+ 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 <vsevik@chromium.org>
Web Inspector: Dialogs style and DialogDelegate interface fixes.
#include "V8Binding.h"
#include "DOMStringList.h"
+#include "DOMWrapperVisitor.h"
#include "Element.h"
#include "MathExtras.h"
#include "PlatformString.h"
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());
#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())
m_stringCache.remove(stringImpl);
}
-
v8::Local<v8::String> StringCache::v8ExternalStringSlow(StringImpl* stringImpl)
{
if (!stringImpl->length())
#if ENABLE(INSPECTOR)
+#include "CharacterData.h"
#include "DOMWrapperVisitor.h"
#include "Document.h"
#include "EventListenerMap.h"
using WebCore::TypeBuilder::Memory::DOMGroup;
using WebCore::TypeBuilder::Memory::ListenerCount;
using WebCore::TypeBuilder::Memory::NodeCount;
+using WebCore::TypeBuilder::Memory::StringStatistics;
namespace WebCore {
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);
}
}
void collectNodeStatistics(Node* node)
{
- collectCharacterData(node);
+ m_characterDataStatistics.collectCharacterData(node);
collectNodeNameInfo(node);
collectListenersInfo(node);
}
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)
{
return;
m_roots.add(rootNode);
- DOMTreeStatistics domTreeStats(rootNode);
+ DOMTreeStatistics domTreeStats(rootNode, m_characterDataStatistics);
RefPtr<DOMGroup> domGroup = DOMGroup::create()
.setSize(domTreeStats.totalNodeCount())
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:
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
{
}
-void InspectorMemoryAgent::getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>& result)
+void InspectorMemoryAgent::getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>& domGroups, RefPtr<InspectorObject>& strings)
{
CounterVisitor counterVisitor(m_page);
ScriptProfiler::visitJSDOMWrappers(&counterVisitor);
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)