comphelper/source/misc/sequenceashashmap.cxx |   13 +++------
 embeddedobj/source/msole/olemisc.cxx         |    8 ++---
 filter/source/config/cache/cacheitem.cxx     |    2 -
 framework/source/services/modulemanager.cxx  |    2 -
 include/comphelper/sequenceashashmap.hxx     |   39 ++++++++++++++++++++++++++-
 package/source/xstor/owriteablestream.cxx    |    2 -
 sw/source/filter/ww8/docxsdrexport.cxx       |   24 +++++++++-------
 7 files changed, 63 insertions(+), 27 deletions(-)

New commits:
commit 22e08a3d8b043ce0ff2424d3fa0a704804afc567
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Fri May 13 15:06:52 2022 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Sat May 14 19:14:19 2022 +0200

    tdf#121740 cache hashcode in SequenceAsHashMap
    
    shaves 2% off load time
    
    Change-Id: I5bd4eabf61205df21a27d2822acd2676a7732a3d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134315
    Tested-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/comphelper/source/misc/sequenceashashmap.cxx 
b/comphelper/source/misc/sequenceashashmap.cxx
index b9662fbddbab..34a6a0c8a580 100644
--- a/comphelper/source/misc/sequenceashashmap.cxx
+++ b/comphelper/source/misc/sequenceashashmap.cxx
@@ -232,7 +232,7 @@ void SequenceAsHashMap::operator>>(css::uno::Sequence< 
css::beans::PropertyValue
                         pThis != end()  ;
                       ++pThis           )
     {
-        pDestination[i].Name  = pThis->first ;
+        pDestination[i].Name  = pThis->first.maString;
         pDestination[i].Value = pThis->second;
         ++i;
     }
@@ -249,7 +249,7 @@ void SequenceAsHashMap::operator>>(css::uno::Sequence< 
css::beans::NamedValue >&
                         pThis != end()  ;
                       ++pThis           )
     {
-        pDestination[i].Name  = pThis->first ;
+        pDestination[i].Name  = pThis->first.maString;
         pDestination[i].Value = pThis->second;
         ++i;
     }
@@ -283,7 +283,7 @@ bool SequenceAsHashMap::match(const SequenceAsHashMap& 
rCheck) const
 {
     for (auto const& elem : rCheck)
     {
-        const OUString& sCheckName  = elem.first;
+        const OUString& sCheckName  = elem.first.maString;
         const css::uno::Any&   aCheckValue = elem.second;
         const_iterator         pFound      = find(sCheckName);
 
@@ -301,12 +301,9 @@ bool SequenceAsHashMap::match(const SequenceAsHashMap& 
rCheck) const
 void SequenceAsHashMap::update(const SequenceAsHashMap& rUpdate)
 {
     m_aMap.reserve(std::max(size(), rUpdate.size()));
-    for (auto const& elem : rUpdate)
+    for (auto const& elem : rUpdate.m_aMap)
     {
-        const OUString& sName  = elem.first;
-        const css::uno::Any&   aValue = elem.second;
-
-        (*this)[sName] = aValue;
+        m_aMap[elem.first] = elem.second;
     }
 }
 
diff --git a/embeddedobj/source/msole/olemisc.cxx 
b/embeddedobj/source/msole/olemisc.cxx
index 8f9a93a65cb4..e1007fbb13cc 100644
--- a/embeddedobj/source/msole/olemisc.cxx
+++ b/embeddedobj/source/msole/olemisc.cxx
@@ -677,11 +677,9 @@ void OleEmbeddedObject::initialize(const 
uno::Sequence<uno::Any>& rArguments)
         return;
 
     comphelper::SequenceAsHashMap aValues(rArguments[0]);
-    for (const auto& rValue : aValues)
-    {
-        if (rValue.first == "StreamReadOnly")
-            rValue.second >>= m_bStreamReadOnly;
-    }
+    auto it = aValues.find("StreamReadOnly");
+    if (it != aValues.end())
+        it->second >>= m_bStreamReadOnly;
 }
 
 OUString SAL_CALL OleEmbeddedObject::getImplementationName()
diff --git a/filter/source/config/cache/cacheitem.cxx 
b/filter/source/config/cache/cacheitem.cxx
index b7993eba1b2d..e39278c2048b 100644
--- a/filter/source/config/cache/cacheitem.cxx
+++ b/filter/source/config/cache/cacheitem.cxx
@@ -95,7 +95,7 @@ css::uno::Sequence< css::beans::PropertyValue > 
CacheItem::getAsPackedPropertyVa
                         pProp != end()  ;
                       ++pProp           )
     {
-        const OUString& rName  = pProp->first;
+        const OUString& rName  = pProp->first.maString;
         const css::uno::Any&   rValue = pProp->second;
 
         if (!rValue.hasValue())
diff --git a/framework/source/services/modulemanager.cxx 
b/framework/source/services/modulemanager.cxx
index ceb8041238be..3e3f9d46949a 100644
--- a/framework/source/services/modulemanager.cxx
+++ b/framework/source/services/modulemanager.cxx
@@ -233,7 +233,7 @@ void SAL_CALL ModuleManager::replaceByName(const OUString& 
sName ,
     {
         // let "NoSuchElementException" out ! We support the same API ...
         // and without a flush() at the end all changed data before will be 
ignored !
-        xModule->replaceByName(prop.first, prop.second);
+        xModule->replaceByName(prop.first.maString, prop.second);
     }
 
     ::comphelper::ConfigurationHelper::flush(xCfg);
diff --git a/include/comphelper/sequenceashashmap.hxx 
b/include/comphelper/sequenceashashmap.hxx
index d6bcd77f0d1a..59ab4c298d76 100644
--- a/include/comphelper/sequenceashashmap.hxx
+++ b/include/comphelper/sequenceashashmap.hxx
@@ -39,7 +39,29 @@ namespace comphelper{
             such name sequences very easy ...
  */
 
-using SequenceAsHashMapBase = std::unordered_map<OUString, css::uno::Any>;
+/** Cache the hash code since calculating it for every comparison adds up */
+struct OUStringAndHashCode
+{
+    OUString maString;
+    sal_Int32 mnHashCode;
+
+    OUStringAndHashCode(OUString s) : maString(s), 
mnHashCode(maString.hashCode()) {}
+};
+struct OUStringAndHashCodeEqual
+{
+    bool operator()(const OUStringAndHashCode & lhs, const OUStringAndHashCode 
& rhs) const
+    {
+        return lhs.mnHashCode == rhs.mnHashCode && lhs.maString == 
rhs.maString;
+    }
+};
+struct OUStringAndHashCodeHash
+{
+    size_t operator()(const OUStringAndHashCode & i) const
+    {
+        return i.mnHashCode;
+    }
+};
+using SequenceAsHashMapBase = std::unordered_map<OUStringAndHashCode, 
css::uno::Any, OUStringAndHashCodeHash, OUStringAndHashCodeEqual>;
 
 class SAL_WARN_UNUSED COMPHELPER_DLLPUBLIC SequenceAsHashMap
 {
@@ -320,6 +342,11 @@ class SAL_WARN_UNUSED COMPHELPER_DLLPUBLIC 
SequenceAsHashMap
             return m_aMap[rKey];
         }
 
+        css::uno::Any& operator[](const OUStringAndHashCode& rKey)
+        {
+            return m_aMap[rKey];
+        }
+
         using iterator = SequenceAsHashMapBase::iterator;
         using const_iterator = SequenceAsHashMapBase::const_iterator;
 
@@ -368,6 +395,16 @@ class SAL_WARN_UNUSED COMPHELPER_DLLPUBLIC 
SequenceAsHashMap
             return m_aMap.find(rKey);
         }
 
+        iterator find(const OUStringAndHashCode& rKey)
+        {
+            return m_aMap.find(rKey);
+        }
+
+        const_iterator find(const OUStringAndHashCode& rKey) const
+        {
+            return m_aMap.find(rKey);
+        }
+
         iterator erase(iterator it)
         {
             return m_aMap.erase(it);
diff --git a/package/source/xstor/owriteablestream.cxx 
b/package/source/xstor/owriteablestream.cxx
index c2f979b61f9d..2a4f1de3f9ef 100644
--- a/package/source/xstor/owriteablestream.cxx
+++ b/package/source/xstor/owriteablestream.cxx
@@ -94,7 +94,7 @@ bool PackageEncryptionDataLessOrEqual( const 
::comphelper::SequenceAsHashMap& aH
         bResult = ( ( aIter->second >>= aKey1 ) && aKey1.hasElements() );
         if ( bResult )
         {
-            const uno::Sequence< sal_Int8 > aKey2 = 
aHash2.getUnpackedValueOrDefault( aIter->first, uno::Sequence< sal_Int8 >() );
+            const uno::Sequence< sal_Int8 > aKey2 = 
aHash2.getUnpackedValueOrDefault( aIter->first.maString, uno::Sequence< 
sal_Int8 >() );
             bResult = aKey1.getLength() == aKey2.getLength()
                 && std::equal(std::cbegin(aKey1), std::cend(aKey1), 
aKey2.begin(), aKey2.end());
         }
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx 
b/sw/source/filter/ww8/docxsdrexport.cxx
index 5e323ee6b937..69dbd4c29091 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -802,15 +802,17 @@ void DocxSdrExport::startDMLAnchorInline(const 
SwFrameFormat* pFrameFormat, cons
             if (it != aGrabBag.end())
             {
                 comphelper::SequenceAsHashMap aAnchorDistDiff(it->second);
-                for (const std::pair<const OUString, uno::Any>& rDiff : 
aAnchorDistDiff)
+                for (const std::pair<const comphelper::OUStringAndHashCode, 
uno::Any>& rDiff :
+                     aAnchorDistDiff)
                 {
-                    if (rDiff.first == "distTDiff" && 
rDiff.second.has<sal_Int32>())
+                    const OUString& rName = rDiff.first.maString;
+                    if (rName == "distTDiff" && rDiff.second.has<sal_Int32>())
                         nDistT -= round(rDiff.second.get<sal_Int32>());
-                    else if (rDiff.first == "distBDiff" && 
rDiff.second.has<sal_Int32>())
+                    else if (rName == "distBDiff" && 
rDiff.second.has<sal_Int32>())
                         nDistB -= round(rDiff.second.get<sal_Int32>());
-                    else if (rDiff.first == "distLDiff" && 
rDiff.second.has<sal_Int32>())
+                    else if (rName == "distLDiff" && 
rDiff.second.has<sal_Int32>())
                         nDistL -= rDiff.second.get<sal_Int32>();
-                    else if (rDiff.first == "distRDiff" && 
rDiff.second.has<sal_Int32>())
+                    else if (rName == "distRDiff" && 
rDiff.second.has<sal_Int32>())
                         nDistR -= rDiff.second.get<sal_Int32>();
                 }
             }
@@ -1159,15 +1161,17 @@ void DocxSdrExport::startDMLAnchorInline(const 
SwFrameFormat* pFrameFormat, cons
             sal_Int64 nTopExtGrabBag(0);
             sal_Int64 nRightExtGrabBag(0);
             sal_Int64 nBottomExtGrabBag(0);
-            for (const std::pair<const OUString, uno::Any>& rDirection : 
aEffectExtent)
+            for (const std::pair<const comphelper::OUStringAndHashCode, 
uno::Any>& rDirection :
+                 aEffectExtent)
             {
-                if (rDirection.first == "l" && 
rDirection.second.has<sal_Int32>())
+                const OUString& rName = rDirection.first.maString;
+                if (rName == "l" && rDirection.second.has<sal_Int32>())
                     nLeftExtGrabBag = rDirection.second.get<sal_Int32>();
-                else if (rDirection.first == "t" && 
rDirection.second.has<sal_Int32>())
+                else if (rName == "t" && rDirection.second.has<sal_Int32>())
                     nTopExtGrabBag = rDirection.second.get<sal_Int32>();
-                else if (rDirection.first == "r" && 
rDirection.second.has<sal_Int32>())
+                else if (rName == "r" && rDirection.second.has<sal_Int32>())
                     nRightExtGrabBag = rDirection.second.get<sal_Int32>();
-                else if (rDirection.first == "b" && 
rDirection.second.has<sal_Int32>())
+                else if (rName == "b" && rDirection.second.has<sal_Int32>())
                     nBottomExtGrabBag = rDirection.second.get<sal_Int32>();
             }
             if (abs(nLeftExtEMU - nLeftExtGrabBag) <= 635 && abs(nTopExtEMU - 
nTopExtGrabBag) <= 635

Reply via email to