Changeset 133372 in webkit
- Timestamp:
- Nov 2, 2012 4:39:42 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r133366 r133372 1 2012-11-02 Elliott Sprehn <esprehn@chromium.org> 2 3 Replace NodeRareData hash map with a union on m_renderer 4 https://bugs.webkit.org/show_bug.cgi?id=100057 5 6 Reviewed by Eric Seidel. 7 8 Use a union on Node::m_renderer between NodeRareData* and RenderObject*. This removes 9 the overhead of accessing rare data and the memory from the map. 10 11 This is an 8% improvement on Bindings/get-elements-by-tag-name.html which tested 12 document.getElementsByTagName and was previously optimized in Bug 90059 for a 5% 13 improvement. As this is better than even the special casing for document that was 14 done in that bug, general node list access should see an even greater win. 15 16 This reduces the memory usage on nytimes.com by 250k per Bug 101052 by 17 removing the rare data map overhead. 18 19 This is also a 15% improvement on Parser/textarea-parsing.html 20 21 By removing the performance overhead of rareData() this patch addresses the performance 22 issues raised in Bugs 73853, 87034 and 89635. 23 24 I ran Parser/html5-full-render.html and there was no performance regression after 25 tuning Text::recalcTextStyle and the refactor that was done in r132684. 26 27 No new tests, this is just a refactor. 28 29 * dom/Document.cpp: 30 (WebCore::Document::Document): 31 * dom/Document.h: 32 (WebCore::Node::Node): 33 * dom/Element.cpp: 34 (WebCore::Element::elementRareData): 35 * dom/Node.cpp: 36 (WebCore::Node::rareData): 37 (WebCore::Node::ensureRareData): 38 (WebCore::Node::clearRareData): 39 (WebCore::Node::renderBox): 40 (WebCore::Node::renderBoxModelObject): 41 (WebCore::Node::reportMemoryUsage): 42 * dom/Node.h: 43 (NodeRareDataBase): 44 Base class for NodeRareData that knows about the renderer so we can 45 inline the accesses in Node.h 46 (WebCore::NodeRareDataBase::renderer): 47 (WebCore::NodeRareDataBase::setRenderer): 48 (WebCore::NodeRareDataBase::~NodeRareDataBase): 49 (WebCore::NodeRareDataBase::NodeRareDataBase): 50 (WebCore): 51 (WebCore::Node::renderer): 52 (WebCore::Node::setRenderer): 53 (Node): 54 * dom/NodeRareData.h: 55 * dom/NodeRenderStyle.h: 56 (WebCore::Node::renderStyle): 57 * dom/Text.cpp: 58 (WebCore::Text::recalcTextStyle): 59 This method appears very hot in html5-full-render.html and accessing the 60 renderer 4 times caused a 2% performance regression with this patch. I 61 reduced it to 1 access and there's no longer any performance regression. 62 * dom/WebCoreMemoryInstrumentation.cpp: 63 Removed tracking of the rare data map memory usage as there is no longer 64 a map to track. 65 * dom/WebCoreMemoryInstrumentation.h: 66 * inspector/InspectorMemoryAgent.cpp: 67 (WebCore::InspectorMemoryAgent::getProcessMemoryDistribution): 68 1 69 2012-11-02 Alexey Proskuryakov <ap@apple.com> 2 70 -
trunk/Source/WebCore/dom/Document.cpp
r133326 r133372 479 479 , m_sawElementsInKnownNamespaces(false) 480 480 , m_isSrcdocDocument(false) 481 , m_documentRareData(0)482 481 , m_eventQueue(DocumentEventQueue::create(this)) 483 482 , m_weakReference(DocumentWeakReference::create(this)) … … 2025 2024 marginBottom = style->marginBottom().isAuto() ? marginBottom : intValueForLength(style->marginBottom(), width, view); 2026 2025 marginLeft = style->marginLeft().isAuto() ? marginLeft : intValueForLength(style->marginLeft(), width, view); 2027 }2028 2029 void Document::setDocumentRareData(NodeRareData* rareData)2030 {2031 m_documentRareData = rareData;2032 2026 } 2033 2027 -
trunk/Source/WebCore/dom/Document.h
r133326 r133372 117 117 class NodeFilter; 118 118 class NodeIterator; 119 class NodeRareData;120 119 class Page; 121 120 class PlatformMouseEvent; … … 467 466 bool isSrcdocDocument() const { return m_isSrcdocDocument; } 468 467 469 NodeRareData* documentRareData() const { return m_documentRareData; };470 void setDocumentRareData(NodeRareData*);471 472 468 StyleResolver* styleResolverIfExists() const { return m_styleResolver.get(); } 473 469 … … 1430 1426 bool m_isSrcdocDocument; 1431 1427 1432 NodeRareData* m_documentRareData;1433 1434 1428 RefPtr<DocumentEventQueue> m_eventQueue; 1435 1429 … … 1527 1521 , m_previous(0) 1528 1522 , m_next(0) 1529 , m_renderer(0)1530 1523 { 1531 1524 if (document) -
trunk/Source/WebCore/dom/Element.cpp
r133326 r133372 155 155 { 156 156 ASSERT(hasRareData()); 157 return static_cast<ElementRareData*>( NodeRareData::rareDataFromMap(this));158 } 159 157 return static_cast<ElementRareData*>(rareData()); 158 } 159 160 160 inline ElementRareData* Element::ensureElementRareData() 161 161 { -
trunk/Source/WebCore/dom/Node.cpp
r133279 r133372 471 471 { 472 472 ASSERT(hasRareData()); 473 NodeRareData* data = isDocumentNode() ? static_cast<const Document*>(this)->documentRareData() : NodeRareData::rareDataFromMap(this); 474 ASSERT(data); 475 return data; 473 return static_cast<NodeRareData*>(m_data.m_rareData); 476 474 } 477 475 … … 482 480 483 481 NodeRareData* data = createRareData().leakPtr(); 484 if (isDocumentNode()) { 485 // Fast path for a Document. A Document knows a pointer to NodeRareData. 486 ASSERT(!static_cast<Document*>(this)->documentRareData()); 487 static_cast<Document*>(this)->setDocumentRareData(data); 488 } else { 489 ASSERT(!NodeRareData::rareDataMap().contains(this)); 490 NodeRareData::rareDataMap().set(this, data); 491 } 482 ASSERT(data); 483 data->setRenderer(m_data.m_renderer); 484 m_data.m_rareData = data; 492 485 setFlag(HasRareDataFlag); 493 486 return data; 494 487 } 495 488 496 489 OwnPtr<NodeRareData> Node::createRareData() 497 490 { … … 507 500 #endif 508 501 509 if (isDocumentNode()) { 510 Document* document = static_cast<Document*>(this); 511 NodeRareData* data = document->documentRareData(); 512 ASSERT(data); 513 delete data; 514 document->setDocumentRareData(0); 515 } else { 516 NodeRareData::NodeRareDataMap& dataMap = NodeRareData::rareDataMap(); 517 NodeRareData::NodeRareDataMap::iterator it = dataMap.find(this); 518 ASSERT(it != dataMap.end()); 519 delete it->value; 520 dataMap.remove(it); 521 } 502 RenderObject* renderer = m_data.m_rareData->renderer(); 503 delete m_data.m_rareData; 504 m_data.m_renderer = renderer; 522 505 clearFlag(HasRareDataFlag); 523 506 } … … 799 782 RenderBox* Node::renderBox() const 800 783 { 801 return m_renderer && m_renderer->isBox() ? toRenderBox(m_renderer) : 0; 784 RenderObject* renderer = this->renderer(); 785 return renderer && renderer->isBox() ? toRenderBox(renderer) : 0; 802 786 } 803 787 804 788 RenderBoxModelObject* Node::renderBoxModelObject() const 805 789 { 806 return m_renderer && m_renderer->isBoxModelObject() ? toRenderBoxModelObject(m_renderer) : 0; 790 RenderObject* renderer = this->renderer(); 791 return renderer && renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0; 807 792 } 808 793 … … 2831 2816 info.addMember(m_next); 2832 2817 info.addMember(m_previous); 2833 if ( m_renderer)2834 info.addMember( m_renderer->style());2818 if (RenderObject* renderer = this->renderer()) 2819 info.addMember(renderer->style()); 2835 2820 if (hasRareData()) 2836 2821 info.addMember(rareData()); -
trunk/Source/WebCore/dom/Node.h
r133286 r133372 112 112 }; 113 113 114 class NodeRareDataBase { 115 public: 116 RenderObject* renderer() const { return m_renderer; } 117 void setRenderer(RenderObject* renderer) { m_renderer = renderer; } 118 virtual ~NodeRareDataBase() { } 119 protected: 120 NodeRareDataBase() { } 121 private: 122 RenderObject* m_renderer; 123 }; 124 114 125 class Node : public EventTarget, public ScriptWrappable, public TreeShared<Node, ContainerNode> { 115 126 friend class Document; … … 500 511 // Integration with rendering tree 501 512 502 RenderObject* renderer() const { return m_renderer; } 503 void setRenderer(RenderObject* renderer) { m_renderer = renderer; } 504 513 // As renderer() includes a branch you should avoid calling it repeatedly in hot code paths. 514 RenderObject* renderer() const { return hasRareData() ? m_data.m_rareData->renderer() : m_data.m_renderer; }; 515 void setRenderer(RenderObject* renderer) 516 { 517 if (hasRareData()) 518 m_data.m_rareData->setRenderer(renderer); 519 else 520 m_data.m_renderer = renderer; 521 } 522 505 523 // Use these two methods with caution. 506 524 RenderBox* renderBox() const; … … 810 828 Node* m_previous; 811 829 Node* m_next; 812 RenderObject* m_renderer; 830 // When a node has rare data we move the renderer into the rare data. 831 union DataUnion { 832 DataUnion() : m_renderer(0) { } 833 RenderObject* m_renderer; 834 NodeRareDataBase* m_rareData; 835 } m_data; 813 836 814 837 protected: -
trunk/Source/WebCore/dom/NodeRareData.h
r133275 r133372 179 179 }; 180 180 181 class NodeRareData {181 class NodeRareData : public NodeRareDataBase { 182 182 WTF_MAKE_NONCOPYABLE(NodeRareData); WTF_MAKE_FAST_ALLOCATED; 183 183 public: … … 201 201 } 202 202 203 typedef HashMap<const Node*, NodeRareData*> NodeRareDataMap;204 205 static NodeRareDataMap& rareDataMap()206 {207 static NodeRareDataMap* dataMap = new NodeRareDataMap;208 return *dataMap;209 }210 211 static NodeRareData* rareDataFromMap(const Node* node)212 {213 return rareDataMap().get(node);214 }215 216 203 TreeScope* treeScope() const { return m_treeScope; } 217 204 void setTreeScope(TreeScope* treeScope) { m_treeScope = treeScope; } -
trunk/Source/WebCore/dom/NodeRenderStyle.h
r132684 r133372 36 36 // Using a ternary here confuses the Solaris Studio 12/12.1/12.2 compilers: 37 37 // Bug is CR 6569194, "Problem with question operator binding in inline function" 38 if ( m_renderer)39 return m_renderer->style();38 if (RenderObject* renderer = this->renderer()) 39 return renderer->style(); 40 40 return nonRendererStyle(); 41 41 } -
trunk/Source/WebCore/dom/Text.cpp
r130190 r133372 257 257 willRecalcTextStyle(change); 258 258 259 if (change != NoChange && parentNode() && parentNode()->renderer()) { 260 if (renderer()) 261 renderer()->setStyle(parentNode()->renderer()->style()); 262 } 259 RenderObject* renderer = this->renderer(); 260 261 // The only time we have a renderer and our parent doesn't is if our parent 262 // is a shadow root. 263 if (change != NoChange && renderer && !parentNode()->isShadowRoot()) 264 renderer->setStyle(parentNode()->renderer()->style()); 265 263 266 if (needsStyleRecalc()) { 264 if (renderer ()) {265 if (renderer ()->isText())266 toRenderText(renderer ())->setText(dataImpl());267 if (renderer) { 268 if (renderer->isText()) 269 toRenderText(renderer)->setText(dataImpl()); 267 270 } else 268 271 reattach(); -
trunk/Source/WebCore/dom/WebCoreMemoryInstrumentation.cpp
r133298 r133372 31 31 #include "config.h" 32 32 #include "WebCoreMemoryInstrumentation.h" 33 34 #include "Node.h"35 #include "NodeRareData.h"36 #include <wtf/MemoryInstrumentationHashMap.h>37 33 38 34 namespace WebCore { … … 77 73 MemoryObjectType WebCoreMemoryTypes::ProcessPrivateMemory = "ProcessPrivateMemory"; 78 74 79 void WebCoreMemoryInstrumentation::reportMemoryUsage(MemoryInstrumentation* memoryInstrumentation)80 {81 memoryInstrumentation->addRootObject(NodeRareData::rareDataMap(), WebCoreMemoryTypes::DOM);82 }83 84 75 } // namespace WebCore -
trunk/Source/WebCore/dom/WebCoreMemoryInstrumentation.h
r133298 r133372 82 82 }; 83 83 84 class WebCoreMemoryInstrumentation {85 public:86 static void reportMemoryUsage(MemoryInstrumentation*);87 };88 89 84 } // namespace WebCore 90 85 -
trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp
r133298 r133372 537 537 RefPtr<InspectorMemoryBlocks> children = InspectorMemoryBlocks::create(); 538 538 addPlatformComponentsInfo(children); 539 WebCoreMemoryInstrumentation::reportMemoryUsage(&memoryInstrumentation);540 539 541 540 memoryInstrumentation.addRootObject(this);
Note: See TracChangeset
for help on using the changeset viewer.