include/svl/itemset.hxx | 1 + sc/inc/patattr.hxx | 3 +++ sc/source/core/data/patattr.cxx | 14 +++++++++++++- svl/source/items/itemset.cxx | 19 +++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-)
New commits: commit 044885e896a441c96a6934b10cbb723fabcf262d Author: Noel Grandin <[email protected]> AuthorDate: Sun Dec 21 19:55:04 2025 +0200 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Sat Dec 27 04:26:54 2025 +0100 tdf#166684 use hashing in CellAttributeHelper::registerAndCheck reduces load time from 1m11s to 33s. Change-Id: I911c101eb8692bf678e6f7147e64e503e9f2bf0a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196062 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx index 9a83cad194d3..ac4050f63a99 100644 --- a/include/svl/itemset.hxx +++ b/include/svl/itemset.hxx @@ -255,6 +255,7 @@ public: const SfxItemSet* GetParent() const { return m_pParent; } bool operator==(const SfxItemSet &) const; + size_t GetHashCode() const; /** Compare possibly ignoring SfxItemPool pointer. diff --git a/sc/inc/patattr.hxx b/sc/inc/patattr.hxx index ab09e64ace83..293f132963ce 100644 --- a/sc/inc/patattr.hxx +++ b/sc/inc/patattr.hxx @@ -130,6 +130,7 @@ class SAL_DLLPUBLIC_RTTI ScPatternAttr final friend class CellAttributeHelper; SfxItemSet maLocalSfxItemSet; + mutable std::optional<size_t> moHashCode; std::optional<OUString> moName; mutable std::optional<bool> mxVisible; mutable std::optional<sal_uInt32> mxNumberFormatKey; @@ -149,6 +150,7 @@ public: SC_DLLPUBLIC ~ScPatternAttr(); bool operator==(const ScPatternAttr& rCmp) const; + size_t GetHashCode() const { if (!moHashCode) CalcHashCode(); return *moHashCode; } // version that allows nullptrs SC_DLLPUBLIC static bool areSame(const ScPatternAttr* pItem1, const ScPatternAttr* pItem2); @@ -287,6 +289,7 @@ private: sal_uInt32 GetNumberFormatKey() const; LanguageType GetLanguageType() const; void InvalidateCaches(); + void CalcHashCode() const; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/patattr.cxx b/sc/source/core/data/patattr.cxx index 3e8f671bb9d7..1baf6cf913ae 100644 --- a/sc/source/core/data/patattr.cxx +++ b/sc/source/core/data/patattr.cxx @@ -115,12 +115,14 @@ const ScPatternAttr* CellAttributeHelper::registerAndCheck(const ScPatternAttr& } const OUString* pCandidateStyleName = rCandidate.GetStyleName(); auto it = maRegisteredCellAttributes.lower_bound(pCandidateStyleName); + const size_t nCandidateHashCode = rCandidate.GetHashCode(); for (; it != maRegisteredCellAttributes.end(); ++it) { const ScPatternAttr* pCheck = *it; if (CompareStringPtr(pCheck->GetStyleName(), pCandidateStyleName) != 0) break; - if (ScPatternAttr::areSame(pCheck, &rCandidate)) + if (nCandidateHashCode == pCheck->GetHashCode() + && ScPatternAttr::areSame(pCheck, &rCandidate)) { pCheck->mnRefCount++; if (bPassingOwnership) @@ -472,6 +474,15 @@ bool ScPatternAttr::operator==(const ScPatternAttr& rCmp) const return maLocalSfxItemSet == rCmp.maLocalSfxItemSet; } +void ScPatternAttr::CalcHashCode() const +{ + size_t nHash = 0; + if (const OUString* pName = GetStyleName()) + nHash = pName->hashCode(); + o3tl::hash_combine(nHash, maLocalSfxItemSet.GetHashCode()); + moHashCode = nHash; +} + bool ScPatternAttr::areSame(const ScPatternAttr* pItem1, const ScPatternAttr* pItem2) { if (pItem1 == pItem2) @@ -1864,6 +1875,7 @@ void ScPatternAttr::InvalidateCaches() mxVisible.reset(); mxNumberFormatKey.reset(); mxLanguageType.reset(); + moHashCode.reset(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx index 3c0d1cbd4783..122e22c2ab78 100644 --- a/svl/source/items/itemset.cxx +++ b/svl/source/items/itemset.cxx @@ -26,6 +26,7 @@ #include <unordered_map> #include <libxml/xmlwriter.h> +#include <o3tl/hash_combine.hxx> #include <sal/log.hxx> #include <svl/itemset.hxx> @@ -1288,6 +1289,24 @@ bool SfxItemSet::Equals(const SfxItemSet &rCmp, bool bComparePool) const return true; } +size_t SfxItemSet::GetHashCode() const +{ + size_t seed = 0; + + for (PoolItemMap::const_iterator it(m_aPoolItemMap.begin()); it != m_aPoolItemMap.end(); it++) + { + const sal_uInt16 nWhich = it->first; + const SfxPoolItem *pItem = it->second; + + o3tl::hash_combine(seed, nWhich); + if (!IsInvalidItem(pItem) && !IsDisabledItem(pItem) + && pItem && pItem->supportsHashCode()) + o3tl::hash_combine(seed, pItem->hashCode()); + } + + return seed; +} + std::unique_ptr<SfxItemSet> SfxItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const { if (pToPool && pToPool != GetPool())
