sc/inc/attarray.hxx              |    4 +++-
 sc/inc/column.hxx                |    3 ++-
 sc/inc/table.hxx                 |    6 ++++--
 sc/source/core/data/attarray.cxx |   25 +++++++++++++++++++------
 sc/source/core/data/column.cxx   |    5 +++--
 sc/source/core/data/document.cxx |    3 ++-
 sc/source/core/data/table2.cxx   |   10 ++++++----
 7 files changed, 39 insertions(+), 17 deletions(-)

New commits:
commit 6716251560b940a5c5113695c86e6be0e2974845
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Mon May 6 10:56:12 2024 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue May 7 16:26:37 2024 +0200

    speed up copy/paste large spreadsheet ranges
    
    The problem is that we are spending a lot of time inside
        SfxItemPool::tryToGetEqualItem
    So cache the result of that call in a map.
    
    Note that this is not needed on master, where the ScPatternAttr
    de-duplication is quite different and a lot more efficient.
    
    Change-Id: I32ca1d140a62ea576d621322696e098b884a783c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167193
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sc/inc/attarray.hxx b/sc/inc/attarray.hxx
index a7e1c08a9f49..59279f95fbc3 100644
--- a/sc/inc/attarray.hxx
+++ b/sc/inc/attarray.hxx
@@ -217,7 +217,9 @@ public:
     void    DeleteArea( SCROW nStartRow, SCROW nEndRow );
     void    MoveTo( SCROW nStartRow, SCROW nEndRow, ScAttrArray& rAttrArray );
     void    CopyArea(
-        SCROW nStartRow, SCROW nEndRow, tools::Long nDy, ScAttrArray& 
rAttrArray, ScMF nStripFlags = ScMF::NONE) const;
+        SCROW nStartRow, SCROW nEndRow, tools::Long nDy, ScAttrArray& 
rAttrArray,
+        std::unordered_map<const ScPatternAttr*, const ScPatternAttr*>* 
pPatternPutCache = nullptr,
+        ScMF nStripFlags = ScMF::NONE) const;
 
     void    DeleteHardAttr( SCROW nStartRow, SCROW nEndRow );
 
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 70b2924aa10b..31ab3574815a 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -344,7 +344,8 @@ public:
     void DeleteRanges( const std::vector<sc::RowSpan>& rRanges, 
InsertDeleteFlags nDelFlag );
 
     void CopyToClip(
-        sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& 
rColumn ) const;
+        sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& 
rColumn,
+        std::unordered_map<const ScPatternAttr*, const ScPatternAttr*>* 
pPatternPutCache = nullptr ) const;
 
     void CopyStaticToDocument(
         SCROW nRow1, SCROW nRow2, const SvNumberFormatterMergeMap& rMap, 
ScColumn& rDestCol );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index d69a07bdf92e..a50e3c75491b 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -539,8 +539,10 @@ public:
         SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags 
nDelFlag,
         bool bBroadcast = true, sc::ColumnSpanSet* pBroadcastSpans = nullptr );
 
-    void CopyToClip( sc::CopyToClipContext& rCxt, SCCOL nCol1, SCROW nRow1, 
SCCOL nCol2, SCROW nRow2, ScTable* pTable );
-    void CopyToClip( sc::CopyToClipContext& rCxt, const ScRangeList& rRanges, 
ScTable* pTable );
+    void CopyToClip( sc::CopyToClipContext& rCxt, SCCOL nCol1, SCROW nRow1, 
SCCOL nCol2, SCROW nRow2, ScTable* pTable,
+                     std::unordered_map<const ScPatternAttr*, const 
ScPatternAttr*>* pPatternPutCache = nullptr );
+    void CopyToClip( sc::CopyToClipContext& rCxt, const ScRangeList& rRanges, 
ScTable* pTable,
+                     std::unordered_map<const ScPatternAttr*, const 
ScPatternAttr*>* pPatternPutCache = nullptr );
 
     void CopyStaticToDocument(
         SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const 
SvNumberFormatterMergeMap& rMap,
diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx
index 4c31fb86e3cc..6d4b2811cd84 100644
--- a/sc/source/core/data/attarray.cxx
+++ b/sc/source/core/data/attarray.cxx
@@ -2433,7 +2433,9 @@ void ScAttrArray::MoveTo(SCROW nStartRow, SCROW nEndRow, 
ScAttrArray& rAttrArray
  * Copy between documents (Clipboard)
  */
 void ScAttrArray::CopyArea(
-    SCROW nStartRow, SCROW nEndRow, tools::Long nDy, ScAttrArray& rAttrArray, 
ScMF nStripFlags) const
+    SCROW nStartRow, SCROW nEndRow, tools::Long nDy, ScAttrArray& rAttrArray,
+    std::unordered_map<const ScPatternAttr*, const ScPatternAttr*>* 
pPatternPutCache,
+    ScMF nStripFlags) const
 {
     nStartRow -= nDy;   // Source
     nEndRow -= nDy;
@@ -2457,7 +2459,7 @@ void ScAttrArray::CopyArea(
         if (mvData[i].nEndRow >= nStartRow)
         {
             const ScPatternAttr* pOldPattern = mvData[i].pPattern;
-            const ScPatternAttr* pNewPattern;
+            const ScPatternAttr* pNewPattern = nullptr;
 
             if (IsDefaultItem( pOldPattern ))
             {
@@ -2484,10 +2486,21 @@ void ScAttrArray::CopyArea(
             }
             else
             {
-                if (bSamePool)
-                    pNewPattern = 
&pDestDocPool->DirectPutItemInPool(*pOldPattern);
-                else
-                    pNewPattern = pOldPattern->PutInPool( 
&rAttrArray.rDocument, &rDocument );
+                if (pPatternPutCache)
+                {
+                    auto it = pPatternPutCache->find(pOldPattern);
+                    if (it != pPatternPutCache->end())
+                        pNewPattern = it->second;
+                }
+                if (!pNewPattern)
+                {
+                    if (bSamePool)
+                        pNewPattern = 
&pDestDocPool->DirectPutItemInPool(*pOldPattern);
+                    else
+                        pNewPattern = pOldPattern->PutInPool( 
&rAttrArray.rDocument, &rDocument );
+                    if (pPatternPutCache)
+                        (*pPatternPutCache)[pOldPattern] = pNewPattern;
+                }
             }
 
             rAttrArray.SetPatternArea(nDestStart,
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 16b9560cc027..4fe1257fe1f4 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -880,10 +880,11 @@ public:
 }
 
 void ScColumn::CopyToClip(
-    sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& rColumn ) 
const
+    sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& rColumn,
+    std::unordered_map<const ScPatternAttr*, const ScPatternAttr*>* 
pPatternPutCache ) const
 {
     if (!rCxt.isCopyChartRanges()) // No need to copy attributes for chart 
ranges
-        pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
+        pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray, 
pPatternPutCache,
                               rCxt.isKeepScenarioFlags() ? (ScMF::All & 
~ScMF::Scenario) : ScMF::All );
 
     {
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index fe3858baae14..9619c9c6077d 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2215,6 +2215,7 @@ void ScDocument::CopyToClip(const ScClipParam& rClipParam,
     CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks);
 
     // 1. Copy selected cells
+    std::unordered_map<const ScPatternAttr*, const ScPatternAttr*> 
aPatternPutCache;
     for (SCTAB i = 0; i < nEndTab; ++i)
     {
         if (!maTabs[i] || i >= pClipDoc->GetTableCount() || 
!pClipDoc->maTabs[i])
@@ -2223,7 +2224,7 @@ void ScDocument::CopyToClip(const ScClipParam& rClipParam,
         if ( pMarks && !pMarks->GetTableSelect(i) )
             continue;
 
-        maTabs[i]->CopyToClip(aCxt, rClipParam.maRanges, 
pClipDoc->maTabs[i].get());
+        maTabs[i]->CopyToClip(aCxt, rClipParam.maRanges, 
pClipDoc->maTabs[i].get(), &aPatternPutCache);
     }
 
     // 2. Copy drawing objects in the selection. Do in after the first "copy 
cells" pass, because
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index fedd0555767e..7f2933529a8a 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -491,7 +491,8 @@ void ScTable::DeleteSelection( InsertDeleteFlags nDelFlag, 
const ScMarkData& rMa
 // pTable = Clipboard
 void ScTable::CopyToClip(
     sc::CopyToClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW 
nRow2,
-    ScTable* pTable )
+    ScTable* pTable,
+    std::unordered_map<const ScPatternAttr*, const ScPatternAttr*>* 
pPatternPutCache )
 {
     if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
         return;
@@ -505,7 +506,7 @@ void ScTable::CopyToClip(
 
     pTable->CreateColumnIfNotExists(nCol2);  // prevent repeated resizing
     for ( SCCOL i = nCol1; i <= nCol2; i++)
-        aCol[i].CopyToClip(rCxt, nRow1, nRow2, 
pTable->CreateColumnIfNotExists(i));  // notes are handled at column level
+        aCol[i].CopyToClip(rCxt, nRow1, nRow2, 
pTable->CreateColumnIfNotExists(i), pPatternPutCache);  // notes are handled at 
column level
 
     //  copy widths/heights, and only "hidden", "filtered" and "manual" flags
     //  also for all preceding columns/rows, to have valid positions for 
drawing objects
@@ -540,12 +541,13 @@ void ScTable::CopyToClip(
 }
 
 void ScTable::CopyToClip(
-    sc::CopyToClipContext& rCxt, const ScRangeList& rRanges, ScTable* pTable )
+    sc::CopyToClipContext& rCxt, const ScRangeList& rRanges, ScTable* pTable,
+    std::unordered_map<const ScPatternAttr*, const ScPatternAttr*>* 
pPatternPutCache )
 {
     for ( size_t i = 0, nListSize = rRanges.size(); i < nListSize; ++i )
     {
         const ScRange & r = rRanges[ i ];
-        CopyToClip( rCxt, r.aStart.Col(), r.aStart.Row(), r.aEnd.Col(), 
r.aEnd.Row(), pTable);
+        CopyToClip( rCxt, r.aStart.Col(), r.aStart.Row(), r.aEnd.Col(), 
r.aEnd.Row(), pTable, pPatternPutCache);
     }
 }
 

Reply via email to