Changeset 132764 in webkit


Ignore:
Timestamp:
Oct 29, 2012, 12:38:01 AM (13 years ago)
Author:
eric@webkit.org
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:
Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r132762 r132764  
     12012-10-29  Eric Seidel  <eric@webkit.org>
     2
     3        Make rendering tables with <colgroups> twice as fast by avoiding walking the DOM for colgroups 4 times for each cell
     4        https://bugs.webkit.org/show_bug.cgi?id=100630
     5
     6        Reviewed by Ojan Vafai.
     7
     8        This is not a complete fix.  Our rendering of this large tables still takes 7.8 seconds
     9        on my retina MBP (down from 14.3s before this change).
     10        It's very expensive to walk the DOM each time we call RenderTable::colElement
     11        so this caches the RenderTableCol* in a vector for easier walking.
     12        We invalidate the cache any time a RenderTableCol is added or removed from the
     13        rendering sub-tree to avoid holding a bad pointer.
     14
     15        * rendering/RenderTable.cpp:
     16        (WebCore::RenderTable::RenderTable):
     17        (WebCore::RenderTable::invalidateCachedColumns):
     18        (WebCore):
     19        (WebCore::RenderTable::addColumn):
     20        (WebCore::RenderTable::removeColumn):
     21        (WebCore::RenderTable::updateColumnCache):
     22        (WebCore::RenderTable::slowColElement):
     23        * rendering/RenderTable.h:
     24        (RenderTable):
     25        * rendering/RenderTableCol.cpp:
     26        (WebCore::RenderTableCol::insertedIntoTree):
     27        (WebCore):
     28        (WebCore::RenderTableCol::willBeRemovedFromTree):
     29        * rendering/RenderTableCol.h:
     30
    1312012-10-28  Kent Tamura  <tkent@chromium.org>
    232
  • trunk/Source/WebCore/rendering/RenderTable.cpp

    r132641 r132764  
    6060    , m_needsSectionRecalc(false)
    6161    , m_columnLogicalWidthChanged(false)
     62    , m_columnRenderersValid(false)
    6263    , m_hSpacing(0)
    6364    , m_vSpacing(0)
     
    214215}
    215216
     217void RenderTable::invalidateCachedColumns()
     218{
     219    m_columnRenderersValid = false;
     220    m_columnRenderers.resize(0);
     221}
     222
     223void RenderTable::addColumn(const RenderTableCol*)
     224{
     225    invalidateCachedColumns();
     226}
     227
     228void RenderTable::removeColumn(const RenderTableCol*)
     229{
     230    invalidateCachedColumns();
     231    // We don't really need to recompute our sections, but we need to update our
     232    // column count and whether we have a column. Currently, we only have one
     233    // size-fit-all flag but we may have to consider splitting it.
     234    setNeedsSectionRecalc();
     235}
     236
    216237void RenderTable::updateLogicalWidth()
    217238{
     
    760781}
    761782
    762 RenderTableCol* RenderTable::slowColElement(unsigned col, bool* startEdge, bool* endEdge) const
     783void RenderTable::updateColumnCache() const
    763784{
    764785    ASSERT(m_hasColElements);
    765 
    766     unsigned columnCount = 0;
     786    ASSERT(m_columnRenderers.isEmpty());
     787    ASSERT(!m_columnRenderersValid);
     788
    767789    for (RenderTableCol* columnRenderer = firstColumn(); columnRenderer; columnRenderer = columnRenderer->nextColumn()) {
    768790        if (columnRenderer->isTableColumnGroupWithColumnChildren())
    769791            continue;
    770 
     792        m_columnRenderers.append(columnRenderer);
     793    }
     794    m_columnRenderersValid = true;
     795}
     796
     797RenderTableCol* RenderTable::slowColElement(unsigned col, bool* startEdge, bool* endEdge) const
     798{
     799    ASSERT(m_hasColElements);
     800
     801    if (!m_columnRenderersValid)
     802        updateColumnCache();
     803
     804    unsigned columnCount = 0;
     805    for (unsigned i = 0; i < m_columnRenderers.size(); i++) {
     806        RenderTableCol* columnRenderer = m_columnRenderers[i];
    771807        unsigned span = columnRenderer->span();
    772808        unsigned startCol = columnCount;
     
    782818        }
    783819    }
    784 
    785820    return 0;
    786821}
  • trunk/Source/WebCore/rendering/RenderTable.h

    r132112 r132764  
    4646    virtual ~RenderTable();
    4747
    48     int getColumnPos(unsigned col) const { return m_columnPos[col]; }
    49 
    5048    // Per CSS 3 writing-mode: "The first and second values of the 'border-spacing' property represent spacing between columns
    5149    // and rows respectively, not necessarily the horizontal and vertical spacing respectively".
     
    259257    void addCaption(const RenderTableCaption*);
    260258    void removeCaption(const RenderTableCaption*);
     259    void addColumn(const RenderTableCol*);
     260    void removeColumn(const RenderTableCol*);
    261261
    262262protected:
     
    284284    RenderTableCol* slowColElement(unsigned col, bool* startEdge, bool* endEdge) const;
    285285
     286    void updateColumnCache() const;
     287    void invalidateCachedColumns();
     288
    286289    virtual RenderBlock* firstLineBlock() const;
    287290    virtual void updateFirstLetter();
     
    306309    mutable Vector<ColumnStruct> m_columns;
    307310    mutable Vector<RenderTableCaption*> m_captions;
     311    mutable Vector<RenderTableCol*> m_columnRenderers;
    308312
    309313    mutable RenderTableSection* m_head;
     
    316320    const CollapsedBorderValue* m_currentBorder;
    317321    bool m_collapsedBordersValid : 1;
    318    
     322
    319323    mutable bool m_hasColElements : 1;
    320324    mutable bool m_needsSectionRecalc : 1;
     325
    321326    bool m_columnLogicalWidthChanged : 1;
     327    mutable bool m_columnRenderersValid: 1;
    322328
    323329    short m_hSpacing;
  • trunk/Source/WebCore/rendering/RenderTableCol.cpp

    r132641 r132764  
    7171}
    7272
     73void RenderTableCol::insertedIntoTree()
     74{
     75    RenderBox::insertedIntoTree();
     76    table()->addColumn(this);
     77}
     78
    7379void RenderTableCol::willBeRemovedFromTree()
    7480{
    7581    RenderBox::willBeRemovedFromTree();
    76 
    77     // We don't really need to recompute our sections, but we need to update our
    78     // column count and whether we have a column. Currently, we only have one
    79     // size-fit-all flag but we may have to consider splitting it.
    80     table()->setNeedsSectionRecalc();
     82    table()->removeColumn(this);
    8183}
    8284
  • trunk/Source/WebCore/rendering/RenderTableCol.h

    r132641 r132764  
    8282    virtual void updateFromElement();
    8383
     84    virtual void insertedIntoTree() OVERRIDE;
    8485    virtual void willBeRemovedFromTree() OVERRIDE;
    8586
Note: See TracChangeset for help on using the changeset viewer.