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); } }