diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2022-03-07 12:48:37 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2022-03-23 09:09:08 +0100 |
commit | 5b490f6e43cb8111157dfddf60fe2e0d053f497c (patch) | |
tree | ea63d3b679820301718f127d1fe801424a0eac75 | |
parent | 74cf42c522e59397bb725d35c682364de032cb99 (diff) |
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 <l.lunak@collabora.com>
-rw-r--r-- | sc/source/filter/excel/xetable.cxx | 38 | ||||
-rw-r--r-- | sc/source/filter/inc/xerecord.hxx | 15 |
2 files changed, 33 insertions, 20 deletions
diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index d790ff74e7eb..dcbcba7251bb 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; |