Changeset 159741 in webkit
- Timestamp:
- Nov 25, 2013 12:22:08 AM (10 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r159737 r159741 1 2013-11-18 Sergio Villar Senin <svillar@igalia.com> 2 3 [CSS Grid Layout] Cache several vectors to avoid malloc/free churn 4 https://bugs.webkit.org/show_bug.cgi?id=123995 5 6 Reviewed by Dean Jackson. 7 8 From Blink r158228 by <jchaffraix@chromium.org> 9 10 Laying-out the grid items means a lot of calls to 11 distributeSpaceToTracks() and 12 resolveContentBasedTrackSizingFunctionsForItems() as they're 13 called in a loop. This means that there is a lot of malloc/free 14 going on there. By moving the vectors used by these methods to a 15 new class which is kept during the whole layout process we save a 16 lot of those calls. 17 18 This obviously mean that the price we pay for a significant 19 perfomance improvement is that we keep the maximum allocation till 20 the end of each layout, but it's an amount of memory that we have 21 to allocate anyway. The improvement in the 22 auto-grid-lots-of-data.html perf test is ~24% (165 runs/s vs 207 23 runs/s). 24 25 No new tests required as we're just refactoring code to a new 26 helper class. Nevertheless the performance improvement is backed 27 by the perf test mentioned above. 28 29 * rendering/RenderGrid.cpp: 30 (WebCore::RenderGrid::GridSizingData::GridSizingData): 31 (WebCore::RenderGrid::computedUsedBreadthOfGridTracks): 32 (WebCore::RenderGrid::resolveContentBasedTrackSizingFunctions): 33 (WebCore::RenderGrid::resolveContentBasedTrackSizingFunctionsForItems): 34 (WebCore::RenderGrid::distributeSpaceToTracks): 35 (WebCore::RenderGrid::layoutGridItems): 36 (WebCore::RenderGrid::findChildLogicalPosition): 37 * rendering/RenderGrid.h: 38 1 39 2013-11-24 Brady Eidson <beidson@apple.com> 2 40 -
trunk/Source/WebCore/rendering/RenderGrid.cpp
r159685 r159741 142 142 }; 143 143 144 class RenderGrid::GridSizingData { 145 WTF_MAKE_NONCOPYABLE(GridSizingData); 146 public: 147 GridSizingData(size_t gridColumnCount, size_t gridRowCount) 148 : columnTracks(gridColumnCount) 149 , rowTracks(gridRowCount) 150 { 151 } 152 153 Vector<GridTrack> columnTracks; 154 Vector<GridTrack> rowTracks; 155 Vector<size_t> contentSizedTracksIndex; 156 157 // Performance optimization: hold onto these Vectors until the end of Layout to avoid repeated malloc / free. 158 Vector<LayoutUnit> distributeTrackVector; 159 Vector<GridTrack*> filteredTracks; 160 }; 161 144 162 RenderGrid::RenderGrid(Element& element, PassRef<RenderStyle> style) 145 163 : RenderBlock(element, std::move(style), 0) … … 277 295 } 278 296 279 void RenderGrid::computedUsedBreadthOfGridTracks(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks)297 void RenderGrid::computedUsedBreadthOfGridTracks(TrackSizingDirection direction, GridSizingData& sizingData) 280 298 { 281 299 LayoutUnit availableLogicalSpace = (direction == ForColumns) ? availableLogicalWidth() : availableLogicalHeight(IncludeMarginBorderPadding); 282 Vector<GridTrack>& tracks = (direction == ForColumns) ? columnTracks :rowTracks;283 Vector<size_t> contentSizedTracks;300 Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks; 301 sizingData.contentSizedTracksIndex.shrink(0); 284 302 for (size_t i = 0; i < tracks.size(); ++i) { 285 303 GridTrack& track = tracks[i]; … … 294 312 295 313 if (trackSize.isContentSized()) 296 contentSizedTracks.append(i);297 } 298 299 if (! contentSizedTracks.isEmpty())300 resolveContentBasedTrackSizingFunctions(direction, columnTracks, rowTracks, contentSizedTracks);314 sizingData.contentSizedTracksIndex.append(i); 315 } 316 317 if (!sizingData.contentSizedTracksIndex.isEmpty()) 318 resolveContentBasedTrackSizingFunctions(direction, sizingData); 301 319 302 320 for (size_t i = 0; i < tracks.size(); ++i) { … … 313 331 tracksForDistribution[i] = tracks.data() + i; 314 332 315 distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth, availableLogicalSpace);333 distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth, sizingData, availableLogicalSpace); 316 334 317 335 // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction. … … 483 501 } 484 502 485 void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, Vector<size_t>& contentSizedTracks)503 void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection direction, GridSizingData& sizingData) 486 504 { 487 505 // FIXME: Split the grid tracks into groups that doesn't overlap a <flex> grid track. 488 506 489 for (size_t i = 0; i < contentSizedTracks.size(); ++i) {490 GridIterator iterator(m_grid, direction, contentSizedTracks[i]);507 for (size_t i = 0; i < sizingData.contentSizedTracksIndex.size(); ++i) { 508 GridIterator iterator(m_grid, direction, sizingData.contentSizedTracksIndex[i]); 491 509 while (RenderBox* gridItem = iterator.nextGridItem()) { 492 resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMinOrMaxContentMinTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);493 resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMaxContentMinTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);494 resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMinOrMaxContentMaxTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);495 resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMaxContentMaxTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);496 } 497 498 GridTrack& track = (direction == ForColumns) ? columnTracks[i] :rowTracks[i];510 resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, gridItem, &GridTrackSize::hasMinOrMaxContentMinTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth); 511 resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, gridItem, &GridTrackSize::hasMaxContentMinTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth); 512 resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, gridItem, &GridTrackSize::hasMinOrMaxContentMaxTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth); 513 resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, gridItem, &GridTrackSize::hasMaxContentMaxTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth); 514 } 515 516 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[i] : sizingData.rowTracks[i]; 499 517 if (track.m_maxBreadth == infinity) 500 518 track.m_maxBreadth = track.m_usedBreadth; … … 502 520 } 503 521 504 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, RenderBox* gridItem, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction)522 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection direction, GridSizingData& sizingData, RenderBox* gridItem, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction) 505 523 { 506 524 const GridCoordinate coordinate = cachedGridCoordinate(gridItem); … … 508 526 const size_t finalTrackIndex = (direction == ForColumns) ? coordinate.columns.finalPositionIndex : coordinate.rows.finalPositionIndex; 509 527 510 Vector<GridTrack*> tracks;528 sizingData.filteredTracks.shrink(0); 511 529 for (size_t trackIndex = initialTrackIndex; trackIndex <= finalTrackIndex; ++trackIndex) { 512 530 const GridTrackSize& trackSize = gridTrackSize(direction, trackIndex); … … 514 532 continue; 515 533 516 GridTrack& track = (direction == ForColumns) ? columnTracks[trackIndex] :rowTracks[trackIndex];517 tracks.append(&track);518 } 519 520 if ( tracks.isEmpty())534 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndex] : sizingData.rowTracks[trackIndex]; 535 sizingData.filteredTracks.append(&track); 536 } 537 538 if (sizingData.filteredTracks.isEmpty()) 521 539 return; 522 540 523 LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItem, direction, columnTracks);541 LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItem, direction, sizingData.columnTracks); 524 542 for (size_t trackIndexForSpace = initialTrackIndex; trackIndexForSpace <= finalTrackIndex; ++trackIndexForSpace) { 525 GridTrack& track = (direction == ForColumns) ? columnTracks[trackIndexForSpace] :rowTracks[trackIndexForSpace];543 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndexForSpace] : sizingData.rowTracks[trackIndexForSpace]; 526 544 additionalBreadthSpace -= (track.*trackGetter)(); 527 545 } 528 546 529 547 // FIXME: We should pass different values for |tracksForGrowthAboveMaxBreadth|. 530 distributeSpaceToTracks( tracks, &tracks, trackGetter, trackGrowthFunction, additionalBreadthSpace);548 distributeSpaceToTracks(sizingData.filteredTracks, &sizingData.filteredTracks, trackGetter, trackGrowthFunction, sizingData, additionalBreadthSpace); 531 549 } 532 550 … … 536 554 } 537 555 538 void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction, LayoutUnit& availableLogicalSpace)556 void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace) 539 557 { 540 558 std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential); 541 559 542 560 size_t tracksSize = tracks.size(); 543 Vector<LayoutUnit> updatedTrackBreadths(tracksSize);561 sizingData.distributeTrackVector.resize(tracksSize); 544 562 545 563 for (size_t i = 0; i < tracksSize; ++i) { … … 549 567 LayoutUnit growthShare = std::max(LayoutUnit(), std::min(availableLogicalSpaceShare, track.m_maxBreadth - trackBreadth)); 550 568 // We should never shrink any grid track or else we can't guarantee we abide by our min-sizing function. 551 updatedTrackBreadths[i] = trackBreadth + growthShare;569 sizingData.distributeTrackVector[i] = trackBreadth + growthShare; 552 570 availableLogicalSpace -= growthShare; 553 571 } … … 557 575 for (size_t i = 0; i < tracksSize; ++i) { 558 576 LayoutUnit growthShare = availableLogicalSpace / (tracksSize - i); 559 updatedTrackBreadths[i] += growthShare;577 sizingData.distributeTrackVector[i] += growthShare; 560 578 availableLogicalSpace -= growthShare; 561 579 } … … 563 581 564 582 for (size_t i = 0; i < tracksSize; ++i) { 565 LayoutUnit growth = updatedTrackBreadths[i] - (tracks[i]->*trackGetter)();583 LayoutUnit growth = sizingData.distributeTrackVector[i] - (tracks[i]->*trackGetter)(); 566 584 if (growth >= 0) 567 585 (tracks[i]->*trackGrowthFunction)(growth); … … 761 779 placeItemsOnGrid(); 762 780 763 Vector<GridTrack> columnTracks(gridColumnCount()); 764 Vector<GridTrack> rowTracks(gridRowCount()); 765 computedUsedBreadthOfGridTracks(ForColumns, columnTracks, rowTracks); 766 ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, columnTracks)); 767 computedUsedBreadthOfGridTracks(ForRows, columnTracks, rowTracks); 768 ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, rowTracks)); 781 GridSizingData sizingData(gridColumnCount(), gridRowCount()); 782 computedUsedBreadthOfGridTracks(ForColumns, sizingData); 783 ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, sizingData.columnTracks)); 784 computedUsedBreadthOfGridTracks(ForRows, sizingData); 785 ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, sizingData.rowTracks)); 769 786 770 787 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { 771 LayoutPoint childPosition = findChildLogicalPosition(child, columnTracks, rowTracks);788 LayoutPoint childPosition = findChildLogicalPosition(child, sizingData); 772 789 773 790 // Because the grid area cannot be styled, we don't need to adjust … … 778 795 // FIXME: For children in a content sized track, we clear the overrideContainingBlockContentLogicalHeight 779 796 // in minContentForChild / maxContentForChild which means that we will always relayout the child. 780 LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChild(child, ForColumns, columnTracks);781 LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadthForChild(child, ForRows, rowTracks);797 LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChild(child, ForColumns, sizingData.columnTracks); 798 LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadthForChild(child, ForRows, sizingData.rowTracks); 782 799 if (oldOverrideContainingBlockContentLogicalWidth != overrideContainingBlockContentLogicalWidth || (oldOverrideContainingBlockContentLogicalHeight != overrideContainingBlockContentLogicalHeight && (child->hasRelativeLogicalHeight() || child->hasViewportPercentageLogicalHeight()))) 783 800 child->setNeedsLayout(MarkOnlyThis); … … 803 820 } 804 821 805 for (size_t i = 0; i < rowTracks.size(); ++i)806 setLogicalHeight(logicalHeight() + rowTracks[i].m_usedBreadth);822 for (size_t i = 0; i < sizingData.rowTracks.size(); ++i) 823 setLogicalHeight(logicalHeight() + sizingData.rowTracks[i].m_usedBreadth); 807 824 808 825 // FIXME: We should handle min / max logical height. … … 1034 1051 } 1035 1052 1036 LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks)1053 LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const GridSizingData& sizingData) 1037 1054 { 1038 1055 const GridCoordinate& coordinate = cachedGridCoordinate(child); … … 1041 1058 LayoutPoint offset(borderAndPaddingStart(), borderAndPaddingBefore()); 1042 1059 // FIXME: |columnTrack| and |rowTrack| should be smaller than our column / row count. 1043 for (size_t i = 0; i < coordinate.columns.initialPositionIndex && i < columnTracks.size(); ++i)1044 offset.setX(offset.x() + columnTracks[i].m_usedBreadth);1045 for (size_t i = 0; i < coordinate.rows.initialPositionIndex && i < rowTracks.size(); ++i)1046 offset.setY(offset.y() + rowTracks[i].m_usedBreadth);1060 for (size_t i = 0; i < coordinate.columns.initialPositionIndex && i < sizingData.columnTracks.size(); ++i) 1061 offset.setX(offset.x() + sizingData.columnTracks[i].m_usedBreadth); 1062 for (size_t i = 0; i < coordinate.rows.initialPositionIndex && i < sizingData.rowTracks.size(); ++i) 1063 offset.setY(offset.y() + sizingData.rowTracks[i].m_usedBreadth); 1047 1064 1048 1065 // FIXME: Handle margins on the grid item. -
trunk/Source/WebCore/rendering/RenderGrid.h
r159684 r159741 65 65 66 66 class GridIterator; 67 class GridSizingData; 67 68 enum TrackSizingDirection { ForColumns, ForRows }; 68 void computedUsedBreadthOfGridTracks(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks);69 void computedUsedBreadthOfGridTracks(TrackSizingDirection, GridSizingData&); 69 70 LayoutUnit computeUsedBreadthOfMinLength(TrackSizingDirection, const GridLength&) const; 70 71 LayoutUnit computeUsedBreadthOfMaxLength(TrackSizingDirection, const GridLength&, LayoutUnit usedBreadth) const; 71 72 LayoutUnit computeUsedBreadthOfSpecifiedLength(TrackSizingDirection, const Length&) const; 72 void resolveContentBasedTrackSizingFunctions(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, Vector<size_t>& contentSizedTracks);73 void resolveContentBasedTrackSizingFunctions(TrackSizingDirection, GridSizingData&); 73 74 74 75 void growGrid(TrackSizingDirection); … … 90 91 typedef void (GridTrack::* AccumulatorGrowFunction)(LayoutUnit); 91 92 typedef bool (GridTrackSize::* FilterFunction)() const; 92 void resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, RenderBox*, FilterFunction, SizingFunction, AccumulatorGetter, AccumulatorGrowFunction);93 void distributeSpaceToTracks(Vector<GridTrack*>&, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter, AccumulatorGrowFunction, LayoutUnit& availableLogicalSpace);93 void resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection, GridSizingData&, RenderBox*, FilterFunction, SizingFunction, AccumulatorGetter, AccumulatorGrowFunction); 94 void distributeSpaceToTracks(Vector<GridTrack*>&, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter, AccumulatorGrowFunction, GridSizingData&, LayoutUnit& availableLogicalSpace); 94 95 95 96 double computeNormalizedFractionBreadth(Vector<GridTrack>&, TrackSizingDirection, LayoutUnit availableLogicalSpace) const; … … 103 104 LayoutUnit minContentForChild(RenderBox*, TrackSizingDirection, Vector<GridTrack>& columnTracks); 104 105 LayoutUnit maxContentForChild(RenderBox*, TrackSizingDirection, Vector<GridTrack>& columnTracks); 105 LayoutPoint findChildLogicalPosition(RenderBox*, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks);106 LayoutPoint findChildLogicalPosition(RenderBox*, const GridSizingData&); 106 107 GridCoordinate cachedGridCoordinate(const RenderBox*) const; 107 108
Note: See TracChangeset
for help on using the changeset viewer.