summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2022-03-07 12:48:37 +0100
committerLuboš Luňák <l.lunak@collabora.com>2022-03-23 09:09:08 +0100
commit5b490f6e43cb8111157dfddf60fe2e0d053f497c (patch)
treeea63d3b679820301718f127d1fe801424a0eac75
parent74cf42c522e59397bb725d35c682364de032cb99 (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.cxx38
-rw-r--r--sc/source/filter/inc/xerecord.hxx15
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;