[Libreoffice-commits] core.git: Branch 'feature/perfwork5' - sc/inc sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Mon Nov 17 14:39:34 PST 2014


 sc/inc/column.hxx                   |    3 -
 sc/inc/table.hxx                    |    3 -
 sc/source/core/data/column3.cxx     |   22 --------
 sc/source/core/data/column4.cxx     |   93 ++++++++++++++++++++++++++++++++++++
 sc/source/core/data/document.cxx    |    9 ++-
 sc/source/core/data/formulacell.cxx |    6 ++
 sc/source/core/data/table2.cxx      |    5 +
 7 files changed, 113 insertions(+), 28 deletions(-)

New commits:
commit dc3a21333fc9c0f98385ccc54035512c5a73dac9
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Nov 17 17:37:07 2014 -0500

    Use group-area listeners during copy & paste if we can.
    
    This should reduce the number of area listeners generated esp. when
    replicating tons of formula cells down the column.
    
    Change-Id: I1ea8f51f667e6b0e1a646f84d79f5e8430b478d5

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 86dbd39..6d8b091 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -255,7 +255,8 @@ public:
     void CopyFromClip(
         sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2, long nDy, ScColumn& rColumn );
 
-    void StartListeningInArea( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 );
+    void StartListeningInArea(
+        sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt, SCROW nRow1, SCROW nRow2 );
 
     void        RemoveEditAttribs( SCROW nStartRow, SCROW nEndRow );
 
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index ea1e2a3..b1e06e1 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -437,7 +437,8 @@ public:
         SCsCOL nDx, SCsROW nDy, ScTable* pTable );
 
     void StartListeningInArea(
-        sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
+        sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt,
+        SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
 
     void SetDirtyFromClip(
         SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans );
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 73c0311..b2a115f 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -1535,28 +1535,6 @@ void ScColumn::StartNeededListeners()
 
 namespace {
 
-class StartListeningInAreaHandler
-{
-    sc::StartListeningContext& mrCxt;
-public:
-    StartListeningInAreaHandler(sc::StartListeningContext& rCxt) : mrCxt(rCxt) {}
-
-    void operator() (size_t /*nRow*/, ScFormulaCell* p)
-    {
-        p->StartListeningTo(mrCxt);
-    }
-};
-
-}
-
-void ScColumn::StartListeningInArea( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 )
-{
-    StartListeningInAreaHandler aFunc(rCxt);
-    sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
-}
-
-namespace {
-
 void applyTextNumFormat( ScColumn& rCol, SCROW nRow, SvNumberFormatter* pFormatter )
 {
     sal_uInt32 nFormat = pFormatter->GetStandardFormat(NUMBERFORMAT_TEXT);
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index f0d28eb..925bb4c 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -1135,4 +1135,97 @@ bool ScColumn::HasFormulaCell( SCROW nRow1, SCROW nRow2 ) const
     return aRet.first != maCells.end();
 }
 
+namespace {
+
+class StartListeningInAreaHandler
+{
+    sc::StartListeningContext& mrStartCxt;
+    sc::EndListeningContext& mrEndCxt;
+
+public:
+    StartListeningInAreaHandler( sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt ) :
+        mrStartCxt(rStartCxt), mrEndCxt(rEndCxt) {}
+
+    void operator() ( const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize )
+    {
+        if (node.type != sc::element_type_formula)
+            // We are only interested in formulas.
+            return;
+
+        ScFormulaCell** ppBeg = &sc::formula_block::at(*node.data, nOffset);
+        ScFormulaCell** ppEnd = ppBeg + nDataSize;
+
+        ScFormulaCell** pp = ppBeg;
+
+        // If the first formula cell belongs to a group and it's not the top
+        // cell, move up to the top cell of the group, and have all the extra
+        // formula cells stop listening.
+
+        ScFormulaCell* pFC = *pp;
+        if (pFC->IsShared() && !pFC->IsSharedTop())
+        {
+            SCROW nBackTrackSize = pFC->aPos.Row() - pFC->GetSharedTopRow();
+            if (nBackTrackSize > 0)
+            {
+                assert(static_cast<size_t>(nBackTrackSize) <= nOffset);
+                for (SCROW i = 0; i < nBackTrackSize; ++i)
+                    --pp;
+                endListening(pp, ppBeg);
+            }
+        }
+
+        for (; pp != ppEnd; ++pp)
+        {
+            pFC = *pp;
+
+            if (!pFC->IsSharedTop())
+            {
+                pFC->StartListeningTo(mrStartCxt);
+                continue;
+            }
+
+            // If This is the last group in the range, see if the group
+            // extends beyond the range, in which case have the excess
+            // formula cells stop listening.
+            size_t nEndGroupPos = (pp - ppBeg) + pFC->GetSharedLength();
+            if (nEndGroupPos > nDataSize)
+            {
+                size_t nExcessSize = nEndGroupPos - nDataSize;
+                ScFormulaCell** ppGrpEnd = pp + pFC->GetSharedLength();
+                ScFormulaCell** ppGrp = ppGrpEnd - nExcessSize;
+                endListening(ppGrp, ppGrpEnd);
+
+                // Register formula cells as a group.
+                sc::SharedFormulaUtil::startListeningAsGroup(mrStartCxt, pp);
+                pp = ppEnd - 1; // Move to the one before the end position.
+            }
+            else
+            {
+                // Register formula cells as a group.
+                sc::SharedFormulaUtil::startListeningAsGroup(mrStartCxt, pp);
+                pp += pFC->GetSharedLength() - 1; // Move to the last one in the group.
+            }
+        }
+    }
+
+private:
+    void endListening( ScFormulaCell** pp, ScFormulaCell** ppEnd )
+    {
+        for (; pp != ppEnd; ++pp)
+        {
+            ScFormulaCell& rFC = **pp;
+            rFC.EndListeningTo(mrEndCxt);
+        }
+    }
+};
+
+}
+
+void ScColumn::StartListeningInArea(
+    sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt, SCROW nRow1, SCROW nRow2 )
+{
+    StartListeningInAreaHandler aFunc(rStartCxt, rEndCxt);
+    sc::ProcessBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index abfe1b0..77e57aa 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2420,12 +2420,17 @@ void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1,
 {
     if (nInsFlag & IDF_CONTENTS)
     {
-        sc::StartListeningContext aCxt(*this);
+        boost::shared_ptr<sc::ColumnBlockPositionSet> pSet(
+            new sc::ColumnBlockPositionSet(*this));
+
+        sc::StartListeningContext aStartCxt(*this, pSet);
+        sc::EndListeningContext aEndCxt(*this, pSet, NULL);
+
         SCTAB nMax = static_cast<SCTAB>(maTabs.size());
         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
         for (; itr != itrEnd && *itr < nMax; ++itr)
             if (maTabs[*itr])
-                maTabs[*itr]->StartListeningInArea(aCxt, nCol1, nRow1, nCol2, nRow2);
+                maTabs[*itr]->StartListeningInArea(aStartCxt, aEndCxt, nCol1, nRow1, nCol2, nRow2);
     }
 }
 
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 0a2226f..ea08c1a 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3941,6 +3941,9 @@ void ScFormulaCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr,
     if (pDoc->IsClipOrUndo() || IsInChangeTrack())
         return;
 
+    if (!HasBroadcaster())
+        return;
+
     pDoc->SetDetectiveDirty(true);  // It has changed something
 
     if ( GetCode()->IsRecalcModeAlways() )
@@ -3983,6 +3986,9 @@ void ScFormulaCell::EndListeningTo( sc::EndListeningContext& rCxt )
     if (rCxt.getDoc().IsClipOrUndo() || IsInChangeTrack())
         return;
 
+    if (!HasBroadcaster())
+        return;
+
     ScDocument& rDoc = rCxt.getDoc();
     rDoc.SetDetectiveDirty(true);  // It has changed something
 
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 8a27333..b6f1441 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1060,13 +1060,14 @@ void ScTable::SetDirtyFromClip(
 }
 
 void ScTable::StartListeningInArea(
-    sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
+    sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt,
+    SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
 {
     if (nCol2 > MAXCOL) nCol2 = MAXCOL;
     if (nRow2 > MAXROW) nRow2 = MAXROW;
     if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
         for (SCCOL i = nCol1; i <= nCol2; i++)
-            aCol[i].StartListeningInArea(rCxt, nRow1, nRow2);
+            aCol[i].StartListeningInArea(rStartCxt, rEndCxt, nRow1, nRow2);
 }
 
 void ScTable::CopyToTable(


More information about the Libreoffice-commits mailing list