Changeset 159684 in webkit


Ignore:
Timestamp:
Nov 22, 2013 1:25:01 AM (10 years ago)
Author:
svillar@igalia.com
Message:

[CSS Grid Layout] Run the content-sized tracks sizing algorithm only when required
https://bugs.webkit.org/show_bug.cgi?id=124039

Reviewed by Dean Jackson.

PerformanceTests:

From Blink r156028 and r156168 by <jchaffraix@chromium.org>.

New performance tests for layouts in grids with fixed size tracks.

  • Layout/fixed-grid-lots-of-data.html: Added.

Source/WebCore:

The current code runs the content sized track sizing algorithm all
the time, which forces a layout even when the track is not
content-sized. This change improves the situation by applying two
optimizations. In the first one, we bail out the algorithm if we
detect that we don't need to run it. And by the second one we
reduce the amount of recomputations by only iterating over the
content sized tracks instead of all of them. Both changes follow
the ideas introduced in Blink r156028 and r156168 by
<jchaffraix@chromium.org>.

As we changed the way we iterate over children (we use the
GridIterator now) the way they're stored in the RenderGrid changes
too. If a item spans through several "cells" inside the grid, we
will have a reference to it on each of them.

These two changes account for a ~3200% improvement on a i7 M620 in
the test that accompanies this change (15.5 vs 520 run/s).

New perf test: PerformanceTests/Layout/fixed-grid-lots-of-data.html

  • rendering/RenderGrid.cpp:

(WebCore::RenderGrid::computedUsedBreadthOfGridTracks): Keep track
of content sized tracks and only iterate over them.
(WebCore::RenderGrid::resolveContentBasedTrackSizingFunctions):
(WebCore::RenderGrid::resolveContentBasedTrackSizingFunctionsForItems):
Early return if there are no tracks to pass to the algorithm.

  • rendering/RenderGrid.h:
  • rendering/style/GridLength.h:

(WebCore::GridLength::isContentSized):

  • rendering/style/GridTrackSize.h:

(WebCore::GridTrackSize::isContentSized):

LayoutTests:

From Blink r156028 and r156168 by <jchaffraix@chromium.org>.

Subtle baseline change due to grids triggering less layouts, which
changes the frame rects between 2 subsequent layouts thus changing
the repaint rectangles.

  • fast/css-grid-layout/grid-item-change-column-repaint-expected.txt:
  • fast/css-grid-layout/grid-item-change-row-repaint-expected.txt:
Location:
trunk
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r159680 r159684  
     12013-11-08  Sergio Villar Senin  <svillar@igalia.com>
     2
     3        [CSS Grid Layout] Run the content-sized tracks sizing algorithm only when required
     4        https://bugs.webkit.org/show_bug.cgi?id=124039
     5
     6        Reviewed by Dean Jackson.
     7
     8        From Blink r156028 and r156168 by <jchaffraix@chromium.org>.
     9
     10        Subtle baseline change due to grids triggering less layouts, which
     11        changes the frame rects between 2 subsequent layouts thus changing
     12        the repaint rectangles.
     13
     14        * fast/css-grid-layout/grid-item-change-column-repaint-expected.txt:
     15        * fast/css-grid-layout/grid-item-change-row-repaint-expected.txt:
     16
    1172013-11-21  Frédéric Wang  <fred.wang@free.fr>
    218
  • trunk/LayoutTests/fast/css-grid-layout/grid-item-change-column-repaint-expected.txt

    r149608 r159684  
    33  (rect 8 38 100 50)
    44  (rect 8 38 50 50)
     5  (rect 8 38 100 50)
    56  (rect 208 38 50 50)
    67)
  • trunk/LayoutTests/fast/css-grid-layout/grid-item-change-row-repaint-expected.txt

    r149608 r159684  
    33  (rect 8 38 100 50)
    44  (rect 8 38 100 100)
     5  (rect 8 38 100 50)
    56  (rect 8 88 100 100)
    67)
  • trunk/PerformanceTests/ChangeLog

    r159488 r159684  
     12013-11-08  Sergio Villar Senin  <svillar@igalia.com>
     2
     3        [CSS Grid Layout] Run the content-sized tracks sizing algorithm only when required
     4        https://bugs.webkit.org/show_bug.cgi?id=124039
     5
     6        Reviewed by Dean Jackson.
     7
     8        From Blink r156028 and r156168 by <jchaffraix@chromium.org>.
     9
     10        New performance tests for layouts in grids with fixed size tracks.
     11
     12        * Layout/fixed-grid-lots-of-data.html: Added.
     13
    1142013-11-19  Manuel Rego Casasnovas  <rego@igalia.com>
    215
  • trunk/Source/WebCore/ChangeLog

    r159683 r159684  
     12013-11-08  Sergio Villar Senin  <svillar@igalia.com>
     2
     3        [CSS Grid Layout] Run the content-sized tracks sizing algorithm only when required
     4        https://bugs.webkit.org/show_bug.cgi?id=124039
     5
     6        Reviewed by Dean Jackson.
     7
     8        The current code runs the content sized track sizing algorithm all
     9        the time, which forces a layout even when the track is not
     10        content-sized. This change improves the situation by applying two
     11        optimizations. In the first one, we bail out the algorithm if we
     12        detect that we don't need to run it. And by the second one we
     13        reduce the amount of recomputations by only iterating over the
     14        content sized tracks instead of all of them. Both changes follow
     15        the ideas introduced in Blink r156028 and r156168 by
     16        <jchaffraix@chromium.org>.
     17
     18        As we changed the way we iterate over children (we use the
     19        GridIterator now) the way they're stored in the RenderGrid changes
     20        too. If a item spans through several "cells" inside the grid, we
     21        will have a reference to it on each of them.
     22
     23        These two changes account for a ~3200% improvement on a i7 M620 in
     24        the test that accompanies this change (15.5 vs 520 run/s).
     25
     26        New perf test: PerformanceTests/Layout/fixed-grid-lots-of-data.html
     27
     28        * rendering/RenderGrid.cpp:
     29        (WebCore::RenderGrid::computedUsedBreadthOfGridTracks): Keep track
     30        of content sized tracks and only iterate over them.
     31        (WebCore::RenderGrid::resolveContentBasedTrackSizingFunctions):
     32        (WebCore::RenderGrid::resolveContentBasedTrackSizingFunctionsForItems):
     33        Early return if there are no tracks to pass to the algorithm.
     34        * rendering/RenderGrid.h:
     35        * rendering/style/GridLength.h:
     36        (WebCore::GridLength::isContentSized):
     37        * rendering/style/GridTrackSize.h:
     38        (WebCore::GridTrackSize::isContentSized):
     39
    1402013-11-22  Manuel Rego Casasnovas  <rego@igalia.com>
    241
  • trunk/Source/WebCore/rendering/RenderGrid.cpp

    r159391 r159684  
    281281    LayoutUnit availableLogicalSpace = (direction == ForColumns) ? availableLogicalWidth() : availableLogicalHeight(IncludeMarginBorderPadding);
    282282    Vector<GridTrack>& tracks = (direction == ForColumns) ? columnTracks : rowTracks;
     283    Vector<size_t> contentSizedTracks;
    283284    for (size_t i = 0; i < tracks.size(); ++i) {
    284285        GridTrack& track = tracks[i];
     
    291292
    292293        track.m_maxBreadth = std::max(track.m_maxBreadth, track.m_usedBreadth);
    293     }
    294 
    295     // FIXME: We shouldn't call resolveContentBasedTrackSizingFunctions if we have no min-content / max-content tracks.
    296     resolveContentBasedTrackSizingFunctions(direction, columnTracks, rowTracks, availableLogicalSpace);
     294
     295        if (trackSize.isContentSized())
     296            contentSizedTracks.append(i);
     297    }
     298
     299    if (!contentSizedTracks.isEmpty())
     300        resolveContentBasedTrackSizingFunctions(direction, columnTracks, rowTracks, contentSizedTracks);
     301
     302    for (size_t i = 0; i < tracks.size(); ++i) {
     303        ASSERT(tracks[i].m_maxBreadth != infinity);
     304        availableLogicalSpace -= tracks[i].m_usedBreadth;
     305    }
    297306
    298307    if (availableLogicalSpace <= 0)
     
    478487}
    479488
    480 void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, LayoutUnit& availableLogicalSpace)
     489void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, Vector<size_t>& contentSizedTracks)
    481490{
    482491    // FIXME: Split the grid tracks into groups that doesn't overlap a <flex> grid track.
    483492
    484     Vector<GridTrack>& tracks = (direction == ForColumns) ? columnTracks : rowTracks;
    485 
    486     // FIXME: Per step 2 of the specification, we should order the grid items by increasing span.
    487     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
    488         resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMinOrMaxContentMinTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
    489         resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMaxContentMinTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
    490         resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMinOrMaxContentMaxTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
    491         resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMaxContentMaxTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
    492     }
    493 
    494     for (size_t i = 0; i < tracks.size(); ++i) {
    495         GridTrack& track = tracks[i];
     493    for (size_t i = 0; i < contentSizedTracks.size(); ++i) {
     494        GridIterator iterator(m_grid, direction, contentSizedTracks[i]);
     495        while (RenderBox* gridItem = iterator.nextGridItem()) {
     496            resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMinOrMaxContentMinTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
     497            resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMaxContentMinTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
     498            resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMinOrMaxContentMaxTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
     499            resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMaxContentMaxTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
     500        }
     501
     502        GridTrack& track = (direction == ForColumns) ? columnTracks[i] : rowTracks[i];
    496503        if (track.m_maxBreadth == infinity)
    497504            track.m_maxBreadth = track.m_usedBreadth;
    498 
    499         availableLogicalSpace -= track.m_usedBreadth;
    500505    }
    501506}
     
    516521        tracks.append(&track);
    517522    }
     523
     524    if (tracks.isEmpty())
     525        return;
    518526
    519527    LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItem, direction, columnTracks);
     
    593601void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coordinate)
    594602{
    595     m_grid[coordinate.rows.initialPositionIndex][coordinate.columns.initialPositionIndex].append(child);
     603    for (size_t row = coordinate.rows.initialPositionIndex; row <= coordinate.rows.finalPositionIndex; ++row) {
     604        for (size_t column = coordinate.columns.initialPositionIndex; column <= coordinate.columns.finalPositionIndex; ++column)
     605            m_grid[row][column].append(child);
     606    }
    596607    m_gridItemCoordinate.set(child, coordinate);
    597608}
  • trunk/Source/WebCore/rendering/RenderGrid.h

    r158115 r159684  
    7070    LayoutUnit computeUsedBreadthOfMaxLength(TrackSizingDirection, const GridLength&, LayoutUnit usedBreadth) const;
    7171    LayoutUnit computeUsedBreadthOfSpecifiedLength(TrackSizingDirection, const Length&) const;
    72     void resolveContentBasedTrackSizingFunctions(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, LayoutUnit& availableLogicalSpace);
     72    void resolveContentBasedTrackSizingFunctions(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, Vector<size_t>& contentSizedTracks);
    7373
    7474    void growGrid(TrackSizingDirection);
  • trunk/Source/WebCore/rendering/style/GridLength.h

    r157393 r159684  
    7474    }
    7575
     76    bool isContentSized() const { return m_type == LengthType && (m_length.isAuto() || m_length.isMinContent() || m_length.isMaxContent()); }
     77
    7678private:
    7779    // Ideally we would put the 2 following fields in a union, but Length has a constructor,
  • trunk/Source/WebCore/rendering/style/GridTrackSize.h

    r157393 r159684  
    9595    GridTrackSizeType type() const { return m_type; }
    9696
     97    bool isContentSized() const { return m_minTrackBreadth.isContentSized() || m_maxTrackBreadth.isContentSized(); }
     98
    9799    bool operator==(const GridTrackSize& other) const
    98100    {
Note: See TracChangeset for help on using the changeset viewer.