include/svl/itemset.hxx | 8 ++++++ include/svl/whiter.hxx | 22 +++++++++++------ svl/source/items/itemset.cxx | 55 +++++++++++++++++++++++++++++++------------ svl/source/items/whiter.cxx | 49 +++++++++++++++++++++++--------------- 4 files changed, 93 insertions(+), 41 deletions(-)
New commits: commit 87a932120d5f146933ed3bcc16c0f47dab90fd4b Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Thu May 26 15:19:42 2022 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Sat May 28 16:00:09 2022 +0200 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.gran...@collabora.co.uk> 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 @@ -308,41 +308,66 @@ void SfxItemSet::InvalidateAllItems() 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: */