[Libreoffice-commits] core.git: 3 commits - sc/inc sc/source

Eike Rathke erack at redhat.com
Tue Oct 14 17:20:48 PDT 2014


 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 <erack at 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 <erack at 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 <erack at 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 )


More information about the Libreoffice-commits mailing list