sc/source/filter/excel/xetable.cxx | 38 +++++++++++++++++-------------------- sc/source/filter/inc/xerecord.hxx | 15 ++++++++++++++ 2 files changed, 33 insertions(+), 20 deletions(-)
New commits: commit 58c6a36bfcc853ca9da81fbc2d071fa50585655b Author: Luboš Luňák <[email protected]> AuthorDate: Mon Mar 7 12:48:37 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Mon Mar 7 15:37:00 2022 +0100 optimize repeated std::vector removal (tdf#126326) Also it's enough to use just pointers to the elements, no need to refcount. Change-Id: I2e6a2f981d75e3dd57aefb41ba1fdbf800fed813 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131107 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index c527d525adba..f9cfc64d4deb 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -1753,31 +1753,31 @@ void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes, bool bXLS ) rXFIndexes.clear(); rXFIndexes.reserve( maColInfos.GetSize() ); - size_t nPos, nSize; - - // do not cache the record list size, it may change in the loop - for( nPos = 0; nPos < maColInfos.GetSize(); ++nPos ) + if( !maColInfos.IsEmpty()) { - XclExpColinfoRef xRec = maColInfos.GetRecord( nPos ); - xRec->ConvertXFIndexes(); - - // try to merge with previous record - if( nPos > 0 ) + XclExpColinfo* xPrevRec = maColInfos.GetRecord( 0 ); + xPrevRec->ConvertXFIndexes(); + for( size_t nPos = 1; nPos < maColInfos.GetSize(); ++nPos ) { - XclExpColinfoRef xPrevRec = maColInfos.GetRecord( nPos - 1 ); + XclExpColinfo* xRec = maColInfos.GetRecord( nPos ); + xRec->ConvertXFIndexes(); + + // try to merge with previous record if( xPrevRec->TryMerge( *xRec ) ) - // adjust nPos to get the next COLINFO record at the same position - maColInfos.RemoveRecord( nPos-- ); + maColInfos.InvalidateRecord( nPos ); + else + xPrevRec = xRec; } + maColInfos.RemoveInvalidatedRecords(); } // put XF indexes into passed vector, collect use count of all different widths std::unordered_map< sal_uInt16, sal_uInt16 > aWidthMap; sal_uInt16 nMaxColCount = 0; sal_uInt16 nMaxUsedWidth = 0; - for( nPos = 0, nSize = maColInfos.GetSize(); nPos < nSize; ++nPos ) + for( size_t nPos = 0; nPos < maColInfos.GetSize(); ++nPos ) { - XclExpColinfoRef xRec = maColInfos.GetRecord( nPos ); + const XclExpColinfo* xRec = maColInfos.GetRecord( nPos ); sal_uInt16 nColCount = xRec->GetColCount(); // add XF index to passed vector @@ -1796,15 +1796,13 @@ void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes, bool bXLS ) maDefcolwidth.SetDefWidth( nMaxUsedWidth, bXLS ); // remove all default COLINFO records - nPos = 0; - while( nPos < maColInfos.GetSize() ) + for( size_t nPos = 0; nPos < maColInfos.GetSize(); ++nPos ) { - XclExpColinfoRef xRec = maColInfos.GetRecord( nPos ); + XclExpColinfo* xRec = maColInfos.GetRecord( nPos ); if( xRec->IsDefault( maDefcolwidth ) ) - maColInfos.RemoveRecord( nPos ); - else - ++nPos; + maColInfos.InvalidateRecord( nPos ); } + maColInfos.RemoveInvalidatedRecords(); } void XclExpColinfoBuffer::Save( XclExpStream& rStrm ) diff --git a/sc/source/filter/inc/xerecord.hxx b/sc/source/filter/inc/xerecord.hxx index 4c37f1b6e7a5..c6901e7fb022 100644 --- a/sc/source/filter/inc/xerecord.hxx +++ b/sc/source/filter/inc/xerecord.hxx @@ -24,6 +24,7 @@ #include "xlstream.hxx" #include <salhelper/simplereferenceobject.hxx> #include <rtl/ref.hxx> +#include <algorithm> // Base classes to export Excel records ======================================= @@ -385,6 +386,20 @@ public: (*aIt)->SaveXml( rStrm ); } + /** + Optimization for repeated removal. Since this is internally a vector, repeated RemoveRecord() + would repeatedly move all items after the removed position. Instead it's possible to invalidate + a record and then call RemoveInvalidatedRecords() at the end (which is necessary, the list is generally + not allowed to contain invalid entries). + */ + void InvalidateRecord( size_t nPos ) { maRecs[ nPos ] = nullptr; } + void RemoveInvalidatedRecords() + { + maRecs.erase( + std::remove_if( maRecs.begin(), maRecs.end(), [](const RecordRefType& xRec) { return xRec == nullptr; } ), + maRecs.end()); + } + private: typedef ::std::vector< RecordRefType > RecordVec; RecordVec maRecs;
