summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2022-05-26 15:19:42 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2022-05-28 16:00:09 +0200
commit87a932120d5f146933ed3bcc16c0f47dab90fd4b (patch)
tree6022b3ff930f5931c39ff29f47259ffc704f4dd5
parent9ea767cb568cef1b142190d2adb0e301baa382e2 (diff)
ofz#24932-1 speed up GetItemState when iterating
by having SfxWhichIter track the current position in the m_ppItems table, which means GetItemState does not need to traverse the ranges table to find the item position. shaves 75% off the time of ./instdir/program/soffice.bin --calc --convert-to pdf ~/Downloads/ofz24932-1.rtf Change-Id: Ib5fe61c75ca05bc2f1932e84b57ccfa55f8b7f74 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135023 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
-rw-r--r--include/svl/itemset.hxx8
-rw-r--r--include/svl/whiter.hxx22
-rw-r--r--svl/source/items/itemset.cxx55
-rw-r--r--svl/source/items/whiter.cxx49
4 files changed, 93 insertions, 41 deletions
diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx
index 7b535fb93d6f..746ba8448afb 100644
--- a/include/svl/itemset.hxx
+++ b/include/svl/itemset.hxx
@@ -23,6 +23,7 @@
#include <cassert>
#include <cstddef>
#include <memory>
+#include <optional>
#include <utility>
#include <svl/svldllapi.h>
@@ -35,6 +36,7 @@ class SfxItemPool;
class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet
{
friend class SfxItemIter;
+ friend class SfxWhichIter;
SfxItemPool* m_pPool; ///< pool that stores the items
const SfxItemSet* m_pParent; ///< derivation
@@ -223,6 +225,12 @@ public:
bool Equals(const SfxItemSet &, bool bComparePool) const;
void dumpAsXml(xmlTextWriterPtr pWriter) const;
+
+private:
+ SfxItemState GetItemStateImpl( sal_uInt16 nWhich,
+ bool bSrchInParent,
+ const SfxPoolItem **ppItem,
+ std::optional<sal_uInt16> oItemsOffsetHint) const;
};
inline void SfxItemSet::SetParent( const SfxItemSet* pNew )
diff --git a/include/svl/whiter.hxx b/include/svl/whiter.hxx
index c4a49a06b622..df8c6fea79f2 100644
--- a/include/svl/whiter.hxx
+++ b/include/svl/whiter.hxx
@@ -16,19 +16,27 @@
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_SVL_WHITER_HXX
-#define INCLUDED_SVL_WHITER_HXX
+#pragma once
#include <svl/svldllapi.h>
#include <svl/whichranges.hxx>
class SfxItemSet;
+class SfxPoolItem;
+enum class SfxItemState;
+/**
+ * Iterates over the which ids and the pool items arrays together (which are stored in parallel arrays).
+ * Primarily so that we can call GetItemSet on the SfxItemSet and pass in a hint, which avoids
+ * searching the array the SfxItemSet, which speeds up GetItemState greatly.
+ */
class SVL_DLLPUBLIC SfxWhichIter
{
- const WhichRangesContainer& pStart;
- const WhichPair* pRanges;
- sal_uInt16 nOffset;
+ const SfxItemSet& m_rItemSet;
+ const WhichPair* m_pCurrentWhichPair;
+ sal_uInt16 m_nOffsetFromStartOfCurrentWhichPair;
+ /// Offset into m_ppItems array in SfxItemSet
+ sal_uInt16 m_nItemsOffset;
public:
SfxWhichIter(const SfxItemSet& rSet);
@@ -36,8 +44,8 @@ public:
sal_uInt16 GetCurWhich() const;
sal_uInt16 NextWhich();
sal_uInt16 FirstWhich();
+ SfxItemState GetItemState(bool bSrchInParent = true,
+ const SfxPoolItem** ppItem = nullptr) const;
};
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx
index 2d90ab16eac7..c96bac69c54d 100644
--- a/svl/source/items/itemset.cxx
+++ b/svl/source/items/itemset.cxx
@@ -309,40 +309,65 @@ SfxItemState SfxItemSet::GetItemState( sal_uInt16 nWhich,
bool bSrchInParent,
const SfxPoolItem **ppItem ) const
{
+ return GetItemStateImpl(nWhich, bSrchInParent, ppItem, std::nullopt);
+}
+
+SfxItemState SfxItemSet::GetItemStateImpl( sal_uInt16 nWhich,
+ bool bSrchInParent,
+ const SfxPoolItem **ppItem,
+ std::optional<sal_uInt16> oItemsOffsetHint) const
+{
// Find the range in which the Which is located
const SfxItemSet* pCurrentSet = this;
SfxItemState eRet = SfxItemState::UNKNOWN;
do
{
- SfxPoolItem const** ppFnd = pCurrentSet->m_ppItems;
- for (const WhichPair& rPair : pCurrentSet->m_pWhichRanges)
+ SfxPoolItem const** pFoundOne = nullptr;
+ if (oItemsOffsetHint)
+ {
+ pFoundOne = pCurrentSet->m_ppItems + *oItemsOffsetHint;
+ assert(!*pFoundOne || IsInvalidItem(*pFoundOne) || (*pFoundOne)->IsVoidItem() || (*pFoundOne)->Which() == nWhich);
+ oItemsOffsetHint.reset(); // in case we need to search parent
+ }
+ else
{
- if ( rPair.first <= nWhich && nWhich <= rPair.second )
+ SfxPoolItem const** ppFnd = pCurrentSet->m_ppItems;
+ for (const WhichPair& rPair : pCurrentSet->m_pWhichRanges)
{
- // Within this range
- ppFnd += nWhich - rPair.first;
- if ( !*ppFnd )
+ if ( rPair.first <= nWhich && nWhich <= rPair.second )
{
- eRet = SfxItemState::DEFAULT;
- if( !bSrchInParent )
- return eRet; // Not present
- break; // Keep searching in the parents!
+ // Within this range
+ pFoundOne = ppFnd + nWhich - rPair.first;
+ break;
}
+ ppFnd += rPair.second - rPair.first + 1;
+ }
+ }
- if ( IsInvalidItem(*ppFnd) )
+ if (pFoundOne)
+ {
+ if ( !*pFoundOne )
+ {
+ eRet = SfxItemState::DEFAULT;
+ if( !bSrchInParent )
+ return eRet; // Not present
+ // Keep searching in the parents!
+ }
+ else
+ {
+ if ( IsInvalidItem(*pFoundOne) )
// Different ones are present
return SfxItemState::DONTCARE;
- if ( (*ppFnd)->IsVoidItem() )
+ if ( (*pFoundOne)->IsVoidItem() )
return SfxItemState::DISABLED;
if (ppItem)
{
- *ppItem = *ppFnd;
+ *ppItem = *pFoundOne;
}
return SfxItemState::SET;
}
- ppFnd += rPair.second - rPair.first + 1;
}
if (!bSrchInParent)
break;
@@ -726,7 +751,7 @@ bool SfxItemSet::Set
continue;
}
const SfxPoolItem* pItem;
- if( SfxItemState::SET == rSet.GetItemState( nWhich1, true, &pItem ) )
+ if( SfxItemState::SET == aIter2.GetItemState( true, &pItem ) )
bRet |= nullptr != Put( *pItem, pItem->Which() );
nWhich1 = aIter1.NextWhich();
nWhich2 = aIter2.NextWhich();
diff --git a/svl/source/items/whiter.cxx b/svl/source/items/whiter.cxx
index 59f2790a530c..707349c70ea5 100644
--- a/svl/source/items/whiter.cxx
+++ b/svl/source/items/whiter.cxx
@@ -17,46 +17,57 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-
-#include <svl/whiter.hxx>
#include <svl/itemset.hxx>
+#include <svl/whiter.hxx>
-SfxWhichIter::SfxWhichIter( const SfxItemSet& rSet ):
- pStart(rSet.GetRanges()),
- pRanges(pStart.begin()),
- nOffset(0)
+SfxWhichIter::SfxWhichIter(const SfxItemSet& rSet)
+ : m_rItemSet(rSet)
+ , m_pCurrentWhichPair(rSet.m_pWhichRanges.begin())
+ , m_nOffsetFromStartOfCurrentWhichPair(0)
+ , m_nItemsOffset(0)
{
}
sal_uInt16 SfxWhichIter::GetCurWhich() const
{
- if ( pRanges >= (pStart.begin() + pStart.size()) )
+ const WhichRangesContainer& rWhichRanges = m_rItemSet.m_pWhichRanges;
+ if (m_pCurrentWhichPair >= (rWhichRanges.begin() + rWhichRanges.size()))
return 0;
- return pRanges->first + nOffset;
+ return m_pCurrentWhichPair->first + m_nOffsetFromStartOfCurrentWhichPair;
}
sal_uInt16 SfxWhichIter::NextWhich()
{
- if ( pRanges >= (pStart.begin() + pStart.size()) )
+ const WhichRangesContainer& rWhichRanges = m_rItemSet.m_pWhichRanges;
+ if (m_pCurrentWhichPair >= (rWhichRanges.begin() + rWhichRanges.size()))
return 0;
- const sal_uInt16 nLastWhich = pRanges->first + nOffset;
- ++nOffset;
- if (pRanges->second == nLastWhich)
+ const sal_uInt16 nLastWhich = m_pCurrentWhichPair->first + m_nOffsetFromStartOfCurrentWhichPair;
+ ++m_nOffsetFromStartOfCurrentWhichPair;
+ if (m_pCurrentWhichPair->second == nLastWhich)
{
- ++pRanges;
- nOffset = 0;
+ m_nItemsOffset += m_pCurrentWhichPair->second - m_pCurrentWhichPair->first + 1;
+ ++m_pCurrentWhichPair;
+ m_nOffsetFromStartOfCurrentWhichPair = 0;
}
- if ( pRanges >= (pStart.begin() + pStart.size()) )
+ if (m_pCurrentWhichPair >= (rWhichRanges.begin() + rWhichRanges.size()))
return 0;
- return pRanges->first + nOffset;
+ return m_pCurrentWhichPair->first + m_nOffsetFromStartOfCurrentWhichPair;
}
sal_uInt16 SfxWhichIter::FirstWhich()
{
- pRanges = pStart.begin();
- nOffset = 0;
- return pRanges->first;
+ m_pCurrentWhichPair = m_rItemSet.m_pWhichRanges.begin();
+ m_nOffsetFromStartOfCurrentWhichPair = 0;
+ m_nItemsOffset = 0;
+ return m_pCurrentWhichPair->first;
+}
+
+SfxItemState SfxWhichIter::GetItemState(bool bSrchInParent, const SfxPoolItem** ppItem) const
+{
+ sal_uInt16 nWhich = m_pCurrentWhichPair->first + m_nOffsetFromStartOfCurrentWhichPair;
+ sal_uInt16 nItemsOffsetHint = m_nItemsOffset + m_nOffsetFromStartOfCurrentWhichPair;
+ return m_rItemSet.GetItemStateImpl(nWhich, bSrchInParent, ppItem, nItemsOffsetHint);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */