sc/inc/markarr.hxx | 1 sc/inc/rangelst.hxx | 1 sc/source/core/data/markarr.cxx | 15 ++++++ sc/source/core/data/markdata.cxx | 17 +++++++ sc/source/core/tool/rangelst.cxx | 49 ++++++++++++++++++++-- sc/source/ui/Accessibility/AccessibleDocument.cxx | 4 - 6 files changed, 78 insertions(+), 9 deletions(-)
New commits: commit defa080e585fb351bc4049b2f280d2e7e5256f6e Author: Eike Rathke <er...@redhat.com> Date: Wed Oct 15 02:03:09 2014 +0200 remove duplicated call to mpChildrenShapes->SelectionChanged() Found when investigating performance bottlenecks of fdo#75486, after the selection is completed ScTabViewObj::getSelection() is called multiple times, each creating a ScCellRangesObj of the range list of filtered ranges, which then is used for ScChildrenShapes::FindSelectedShapesChanges() The duplicated call was introduced with b41332475783c31136673fb44cf4c411bb0148f8 but IMHO does not make any sense at all unless it has obscure side effects, it only slows down things even more. Change-Id: I3cee2e3e62c24ad72efb8cc2021e74d0afc70b69 diff --git a/sc/source/ui/Accessibility/AccessibleDocument.cxx b/sc/source/ui/Accessibility/AccessibleDocument.cxx index 975dfc7..751a9fe 100644 --- a/sc/source/ui/Accessibility/AccessibleDocument.cxx +++ b/sc/source/ui/Accessibility/AccessibleDocument.cxx @@ -1691,10 +1691,6 @@ void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& / CommitChange(aEvent); } - if(mpChildrenShapes ) - { - mpChildrenShapes->SelectionChanged(); - } } //===== XInterface ===================================================== commit 94efc482d514bf9c6c4edb149f86084d672b724f Author: Eike Rathke <er...@redhat.com> Date: Tue Oct 14 23:50:24 2014 +0200 speed up simple range list joins that could be appends, fdo#75486 related Change-Id: I734ff88bc4c0633875c9e9c19a817b8b08511c83 diff --git a/sc/inc/rangelst.hxx b/sc/inc/rangelst.hxx index 897bb97..4a10eed 100644 --- a/sc/inc/rangelst.hxx +++ b/sc/inc/rangelst.hxx @@ -93,6 +93,7 @@ public: private: ::std::vector<ScRange*> maRanges; + SCROW mnMaxRowUsed; typedef std::vector<ScRange*>::iterator iterator; typedef std::vector<ScRange*>::const_iterator const_iterator; }; diff --git a/sc/source/core/tool/rangelst.cxx b/sc/source/core/tool/rangelst.cxx index 6e276bc..ab5653f5 100644 --- a/sc/source/core/tool/rangelst.cxx +++ b/sc/source/core/tool/rangelst.cxx @@ -229,6 +229,37 @@ void ScRangeList::Join( const ScRange& r, bool bIsInList ) SCROW nRow2 = r.aEnd.Row(); SCTAB nTab2 = r.aEnd.Tab(); + // One common usage is to join ranges that actually are top to bottom + // appends but the caller doesn't exactly know about it, e.g. when invoked + // by ScMarkData::FillRangeListWithMarks(), check for this special case + // first and speed up things by not looping over all ranges for each range + // to be joined. We don't remember the exact encompassing range that would + // have to be updated on refupdates and insertions and deletions, instead + // remember just the maximum row used, even independently of the sheet. + // This satisfies most use cases. + + if (!bIsInList) + { + if (nRow1 > mnMaxRowUsed + 1) + { + Append( r ); + return; + } + else if (nRow1 == mnMaxRowUsed + 1) + { + // Check if we can simply enlarge the last range. + ScRange* p = maRanges.back(); + if (p->aEnd.Row() + 1 == nRow1 && + p->aStart.Col() == nCol1 && p->aEnd.Col() == nCol2 && + p->aStart.Tab() == nTab1 && p->aEnd.Tab() == nTab2) + { + p->aEnd.SetRow( nRow2 ); + mnMaxRowUsed = nRow2; + return; + } + } + } + ScRange* pOver = (ScRange*) &r; // fies aber wahr wenn bInList size_t nOldPos = 0; if ( bIsInList ) @@ -403,6 +434,8 @@ bool ScRangeList::UpdateReference( bChanged = true; pR->aStart.Set( theCol1, theRow1, theTab1 ); pR->aEnd.Set( theCol2, theRow2, theTab2 ); + if (mnMaxRowUsed < theRow2) + mnMaxRowUsed = theRow2; } } @@ -435,6 +468,8 @@ void ScRangeList::InsertRow( SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW n SCROW nNewRangeEndRow = nRowPos + nSize - 1; aNewRanges.push_back(ScRange(nNewRangeStartCol, nNewRangeStartRow, nTab, nNewRangeEndCol, nNewRangeEndRow, nTab)); + if (mnMaxRowUsed < nNewRangeEndRow) + mnMaxRowUsed = nNewRangeEndRow; } } } @@ -983,16 +1018,19 @@ ScRange* ScRangeList::Find( const ScAddress& rAdr ) return itr == maRanges.end() ? NULL : *itr; } -ScRangeList::ScRangeList() {} +ScRangeList::ScRangeList() : mnMaxRowUsed(-1) {} ScRangeList::ScRangeList( const ScRangeList& rList ) : - SvRefBase() + SvRefBase(), + mnMaxRowUsed(-1) { maRanges.reserve(rList.maRanges.size()); for_each(rList.maRanges.begin(), rList.maRanges.end(), AppendToList(maRanges)); + mnMaxRowUsed = rList.mnMaxRowUsed; } -ScRangeList::ScRangeList( const ScRange& rRange ) +ScRangeList::ScRangeList( const ScRange& rRange ) : + mnMaxRowUsed(-1) { maRanges.reserve(1); Append(rRange); @@ -1003,13 +1041,14 @@ ScRangeList& ScRangeList::operator=(const ScRangeList& rList) RemoveAll(); maRanges.reserve(rList.maRanges.size()); for_each(rList.maRanges.begin(), rList.maRanges.end(), AppendToList(maRanges)); + mnMaxRowUsed = rList.mnMaxRowUsed; return *this; } void ScRangeList::Append( const ScRange& rRange ) { ScRange* pR = new ScRange( rRange ); - maRanges.push_back( pR ); + push_back( pR ); } bool ScRangeList::Intersects( const ScRange& rRange ) const @@ -1126,6 +1165,8 @@ const ScRange* ScRangeList::back() const void ScRangeList::push_back(ScRange* p) { maRanges.push_back(p); + if (mnMaxRowUsed < p->aEnd.Row()) + mnMaxRowUsed = p->aEnd.Row(); } ScAddress ScRangeList::GetTopLeftCorner() const commit 268d5a7e3c5b31ad22bce7ff36a68c5d13fe7a40 Author: Eike Rathke <er...@redhat.com> Date: Tue Oct 14 23:47:40 2014 +0200 speed up range list generation from multi marks, fdo#75486 related Change-Id: Id2114652948d12c92b0e7be7afa304bfffc8fbe0 diff --git a/sc/inc/markarr.hxx b/sc/inc/markarr.hxx index 5b15d42..2988fe4 100644 --- a/sc/inc/markarr.hxx +++ b/sc/inc/markarr.hxx @@ -47,6 +47,7 @@ public: void SetMarkArea( SCROW nStartRow, SCROW nEndRow, bool bMarked ); bool IsAllMarked( SCROW nStartRow, SCROW nEndRow ) const; bool HasOneMark( SCROW& rStartRow, SCROW& rEndRow ) const; + bool HasEqualRowsMarked( const ScMarkArray& rOther ) const; bool HasMarks() const { return ( nCount > 1 || ( nCount == 1 && pData[0].bMarked ) ); } diff --git a/sc/source/core/data/markarr.cxx b/sc/source/core/data/markarr.cxx index 00e3ce0..407fad5 100644 --- a/sc/source/core/data/markarr.cxx +++ b/sc/source/core/data/markarr.cxx @@ -274,6 +274,21 @@ bool ScMarkArray::HasOneMark( SCROW& rStartRow, SCROW& rEndRow ) const return bRet; } +bool ScMarkArray::HasEqualRowsMarked( const ScMarkArray& rOther ) const +{ + if (nCount != rOther.nCount) + return false; + + for (size_t i=0; i < nCount; ++i) + { + if (pData[i].bMarked != rOther.pData[i].bMarked || + pData[i].nRow != rOther.pData[i].nRow) + return false; + } + + return true; +} + void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const { delete[] rDestMarkArray.pData; diff --git a/sc/source/core/data/markdata.cxx b/sc/source/core/data/markdata.cxx index 482882e..022a820 100644 --- a/sc/source/core/data/markdata.cxx +++ b/sc/source/core/data/markdata.cxx @@ -386,10 +386,23 @@ void ScMarkData::FillRangeListWithMarks( ScRangeList* pList, bool bClear ) const SCCOL nStartCol = aMultiRange.aStart.Col(); SCCOL nEndCol = aMultiRange.aEnd.Col(); for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++) + { if (pMultiSel[nCol].HasMarks()) { + // Feeding column-wise fragments to ScRangeList::Join() is a + // huge bottleneck, speed this up for multiple columns + // consisting of identical row sets by building a column span + // first. This is usually the case for filtered data, for + // example. + SCCOL nToCol = nCol+1; + for ( ; nToCol <= nEndCol; ++nToCol) + { + if (!pMultiSel[nCol].HasEqualRowsMarked( pMultiSel[nToCol])) + break; + } + --nToCol; + ScRange aRange( nCol, 0, nTab, nToCol, 0, nTab ); SCROW nTop, nBottom; - ScRange aRange( nCol, 0, nTab ); ScMarkArrayIter aMarkIter( &pMultiSel[nCol] ); while ( aMarkIter.Next( nTop, nBottom ) ) { @@ -397,7 +410,9 @@ void ScMarkData::FillRangeListWithMarks( ScRangeList* pList, bool bClear ) const aRange.aEnd.SetRow( nBottom ); pList->Join( aRange ); } + nCol = nToCol; } + } } if ( bMarked ) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits