Title: [132764] trunk/Source/WebCore
Revision
132764
Author
[email protected]
Date
2012-10-29 00:38:01 -0700 (Mon, 29 Oct 2012)

Log Message

Make rendering tables with <colgroups> twice as fast by avoiding walking the DOM for colgroups 4 times for each cell
https://bugs.webkit.org/show_bug.cgi?id=100630

Reviewed by Ojan Vafai.

This is not a complete fix.  Our rendering of this large tables still takes 7.8 seconds
on my retina MBP (down from 14.3s before this change).
It's very expensive to walk the DOM each time we call RenderTable::colElement
so this caches the RenderTableCol* in a vector for easier walking.
We invalidate the cache any time a RenderTableCol is added or removed from the
rendering sub-tree to avoid holding a bad pointer.

* rendering/RenderTable.cpp:
(WebCore::RenderTable::RenderTable):
(WebCore::RenderTable::invalidateCachedColumns):
(WebCore):
(WebCore::RenderTable::addColumn):
(WebCore::RenderTable::removeColumn):
(WebCore::RenderTable::updateColumnCache):
(WebCore::RenderTable::slowColElement):
* rendering/RenderTable.h:
(RenderTable):
* rendering/RenderTableCol.cpp:
(WebCore::RenderTableCol::insertedIntoTree):
(WebCore):
(WebCore::RenderTableCol::willBeRemovedFromTree):
* rendering/RenderTableCol.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (132763 => 132764)


--- trunk/Source/WebCore/ChangeLog	2012-10-29 07:29:43 UTC (rev 132763)
+++ trunk/Source/WebCore/ChangeLog	2012-10-29 07:38:01 UTC (rev 132764)
@@ -1,3 +1,33 @@
+2012-10-29  Eric Seidel  <[email protected]>
+
+        Make rendering tables with <colgroups> twice as fast by avoiding walking the DOM for colgroups 4 times for each cell
+        https://bugs.webkit.org/show_bug.cgi?id=100630
+
+        Reviewed by Ojan Vafai.
+
+        This is not a complete fix.  Our rendering of this large tables still takes 7.8 seconds
+        on my retina MBP (down from 14.3s before this change).
+        It's very expensive to walk the DOM each time we call RenderTable::colElement
+        so this caches the RenderTableCol* in a vector for easier walking.
+        We invalidate the cache any time a RenderTableCol is added or removed from the
+        rendering sub-tree to avoid holding a bad pointer.
+
+        * rendering/RenderTable.cpp:
+        (WebCore::RenderTable::RenderTable):
+        (WebCore::RenderTable::invalidateCachedColumns):
+        (WebCore):
+        (WebCore::RenderTable::addColumn):
+        (WebCore::RenderTable::removeColumn):
+        (WebCore::RenderTable::updateColumnCache):
+        (WebCore::RenderTable::slowColElement):
+        * rendering/RenderTable.h:
+        (RenderTable):
+        * rendering/RenderTableCol.cpp:
+        (WebCore::RenderTableCol::insertedIntoTree):
+        (WebCore):
+        (WebCore::RenderTableCol::willBeRemovedFromTree):
+        * rendering/RenderTableCol.h:
+
 2012-10-28  Kent Tamura  <[email protected]>
 
         Rename Localizer.{cpp,h} to PlatformLocale.{cpp,h}

Modified: trunk/Source/WebCore/rendering/RenderTable.cpp (132763 => 132764)


--- trunk/Source/WebCore/rendering/RenderTable.cpp	2012-10-29 07:29:43 UTC (rev 132763)
+++ trunk/Source/WebCore/rendering/RenderTable.cpp	2012-10-29 07:38:01 UTC (rev 132764)
@@ -59,6 +59,7 @@
     , m_hasColElements(false)
     , m_needsSectionRecalc(false)
     , m_columnLogicalWidthChanged(false)
+    , m_columnRenderersValid(false)
     , m_hSpacing(0)
     , m_vSpacing(0)
     , m_borderStart(0)
@@ -213,6 +214,26 @@
     m_captions.remove(index);
 }
 
+void RenderTable::invalidateCachedColumns()
+{
+    m_columnRenderersValid = false;
+    m_columnRenderers.resize(0);
+}
+
+void RenderTable::addColumn(const RenderTableCol*)
+{
+    invalidateCachedColumns();
+}
+
+void RenderTable::removeColumn(const RenderTableCol*)
+{
+    invalidateCachedColumns();
+    // We don't really need to recompute our sections, but we need to update our
+    // column count and whether we have a column. Currently, we only have one
+    // size-fit-all flag but we may have to consider splitting it.
+    setNeedsSectionRecalc();
+}
+
 void RenderTable::updateLogicalWidth()
 {
     recalcSectionsIfNeeded();
@@ -759,15 +780,30 @@
     return 0;
 }
 
-RenderTableCol* RenderTable::slowColElement(unsigned col, bool* startEdge, bool* endEdge) const
+void RenderTable::updateColumnCache() const
 {
     ASSERT(m_hasColElements);
+    ASSERT(m_columnRenderers.isEmpty());
+    ASSERT(!m_columnRenderersValid);
 
-    unsigned columnCount = 0;
     for (RenderTableCol* columnRenderer = firstColumn(); columnRenderer; columnRenderer = columnRenderer->nextColumn()) {
         if (columnRenderer->isTableColumnGroupWithColumnChildren())
             continue;
+        m_columnRenderers.append(columnRenderer);
+    }
+    m_columnRenderersValid = true;
+}
 
+RenderTableCol* RenderTable::slowColElement(unsigned col, bool* startEdge, bool* endEdge) const
+{
+    ASSERT(m_hasColElements);
+
+    if (!m_columnRenderersValid)
+        updateColumnCache();
+
+    unsigned columnCount = 0;
+    for (unsigned i = 0; i < m_columnRenderers.size(); i++) {
+        RenderTableCol* columnRenderer = m_columnRenderers[i];
         unsigned span = columnRenderer->span();
         unsigned startCol = columnCount;
         ASSERT(span >= 1);
@@ -781,7 +817,6 @@
             return columnRenderer;
         }
     }
-
     return 0;
 }
 

Modified: trunk/Source/WebCore/rendering/RenderTable.h (132763 => 132764)


--- trunk/Source/WebCore/rendering/RenderTable.h	2012-10-29 07:29:43 UTC (rev 132763)
+++ trunk/Source/WebCore/rendering/RenderTable.h	2012-10-29 07:38:01 UTC (rev 132764)
@@ -45,8 +45,6 @@
     explicit RenderTable(Node*);
     virtual ~RenderTable();
 
-    int getColumnPos(unsigned col) const { return m_columnPos[col]; }
-
     // Per CSS 3 writing-mode: "The first and second values of the 'border-spacing' property represent spacing between columns
     // and rows respectively, not necessarily the horizontal and vertical spacing respectively".
     int hBorderSpacing() const { return m_hSpacing; }
@@ -258,6 +256,8 @@
 
     void addCaption(const RenderTableCaption*);
     void removeCaption(const RenderTableCaption*);
+    void addColumn(const RenderTableCol*);
+    void removeColumn(const RenderTableCol*);
 
 protected:
     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
@@ -283,6 +283,9 @@
 
     RenderTableCol* slowColElement(unsigned col, bool* startEdge, bool* endEdge) const;
 
+    void updateColumnCache() const;
+    void invalidateCachedColumns();
+
     virtual RenderBlock* firstLineBlock() const;
     virtual void updateFirstLetter();
     
@@ -305,6 +308,7 @@
     mutable Vector<int> m_columnPos;
     mutable Vector<ColumnStruct> m_columns;
     mutable Vector<RenderTableCaption*> m_captions;
+    mutable Vector<RenderTableCol*> m_columnRenderers;
 
     mutable RenderTableSection* m_head;
     mutable RenderTableSection* m_foot;
@@ -315,10 +319,12 @@
     CollapsedBorderValues m_collapsedBorders;
     const CollapsedBorderValue* m_currentBorder;
     bool m_collapsedBordersValid : 1;
-    
+
     mutable bool m_hasColElements : 1;
     mutable bool m_needsSectionRecalc : 1;
+
     bool m_columnLogicalWidthChanged : 1;
+    mutable bool m_columnRenderersValid: 1;
 
     short m_hSpacing;
     short m_vSpacing;

Modified: trunk/Source/WebCore/rendering/RenderTableCol.cpp (132763 => 132764)


--- trunk/Source/WebCore/rendering/RenderTableCol.cpp	2012-10-29 07:29:43 UTC (rev 132763)
+++ trunk/Source/WebCore/rendering/RenderTableCol.cpp	2012-10-29 07:38:01 UTC (rev 132764)
@@ -70,14 +70,16 @@
         setNeedsLayoutAndPrefWidthsRecalc();
 }
 
+void RenderTableCol::insertedIntoTree()
+{
+    RenderBox::insertedIntoTree();
+    table()->addColumn(this);
+}
+
 void RenderTableCol::willBeRemovedFromTree()
 {
     RenderBox::willBeRemovedFromTree();
-
-    // We don't really need to recompute our sections, but we need to update our
-    // column count and whether we have a column. Currently, we only have one
-    // size-fit-all flag but we may have to consider splitting it.
-    table()->setNeedsSectionRecalc();
+    table()->removeColumn(this);
 }
 
 bool RenderTableCol::isChildAllowed(RenderObject* child, RenderStyle* style) const

Modified: trunk/Source/WebCore/rendering/RenderTableCol.h (132763 => 132764)


--- trunk/Source/WebCore/rendering/RenderTableCol.h	2012-10-29 07:29:43 UTC (rev 132763)
+++ trunk/Source/WebCore/rendering/RenderTableCol.h	2012-10-29 07:38:01 UTC (rev 132764)
@@ -81,6 +81,7 @@
     virtual bool isRenderTableCol() const OVERRIDE { return true; }
     virtual void updateFromElement();
 
+    virtual void insertedIntoTree() OVERRIDE;
     virtual void willBeRemovedFromTree() OVERRIDE;
 
     virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to