diff options
author | Noel Grandin <noel@peralex.com> | 2021-01-26 20:29:23 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-01-27 07:38:13 +0100 |
commit | b2ebceeaf49aa45979486997e6358697b7045361 (patch) | |
tree | 983c44d67b014256e38a3ac7bef708f278c217cb /svl | |
parent | e58d2561f93271879252c2d0eda6cf1a08ef9848 (diff) |
tdf#92456 store hash with string
so it does not need re-computing when comparing keys.
shave 5% off time for this bug.
Change-Id: I48870567be00f0ea98cad69e9c48222cd64decf2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/109992
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'svl')
-rw-r--r-- | svl/source/misc/sharedstringpool.cxx | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/svl/source/misc/sharedstringpool.cxx b/svl/source/misc/sharedstringpool.cxx index 9ddb64fff88b..997648fac363 100644 --- a/svl/source/misc/sharedstringpool.cxx +++ b/svl/source/misc/sharedstringpool.cxx @@ -15,6 +15,36 @@ #include <unordered_map> #include <unordered_set> +/** create a key class that caches the hashcode */ +namespace +{ +struct StringWithHash +{ + OUString str; + sal_Int32 hashCode; + StringWithHash(OUString s) + : str(s) + , hashCode(s.hashCode()) + { + } + + bool operator==(StringWithHash const& rhs) const + { + if (hashCode != rhs.hashCode) + return false; + return str == rhs.str; + } +}; +} + +namespace std +{ +template <> struct hash<StringWithHash> +{ + std::size_t operator()(const StringWithHash& k) const { return k.hashCode; } +}; +} + namespace svl { namespace @@ -28,7 +58,7 @@ struct SharedStringPool::Impl // We use this map for two purposes - to store lower->upper case mappings // and to retrieve a shared uppercase object, so the management logic // is quite complex. - std::unordered_map<OUString, OUString> maStrMap; + std::unordered_map<StringWithHash, OUString> maStrMap; const CharClass& mrCharClass; explicit Impl(const CharClass& rCharClass) @@ -46,35 +76,37 @@ SharedStringPool::~SharedStringPool() {} SharedString SharedStringPool::intern(const OUString& rStr) { + StringWithHash aStrWithHash(rStr); osl::MutexGuard aGuard(&mpImpl->maMutex); - auto[mapIt, bInserted] = mpImpl->maStrMap.emplace(rStr, rStr); + auto[mapIt, bInserted] = mpImpl->maStrMap.emplace(aStrWithHash, rStr); if (!bInserted) // there is already a mapping - return SharedString(mapIt->first.pData, mapIt->second.pData); + return SharedString(mapIt->first.str.pData, mapIt->second.pData); // This is a new string insertion. Establish mapping to upper-case variant. OUString aUpper = mpImpl->mrCharClass.uppercase(rStr); if (aUpper == rStr) // no need to do anything more, because we inserted an upper->upper mapping - return SharedString(mapIt->first.pData, mapIt->second.pData); + return SharedString(mapIt->first.str.pData, mapIt->second.pData); // We need to insert a lower->upper mapping, so also insert // an upper->upper mapping, which we can use both for when an upper string // is interned, and to look up a shared upper string. - auto mapIt2 = mpImpl->maStrMap.find(aUpper); + StringWithHash aUpperWithHash(aUpper); + auto mapIt2 = mpImpl->maStrMap.find(aUpperWithHash); if (mapIt2 != mpImpl->maStrMap.end()) { // there is an already existing upper string - mapIt->second = mapIt2->first; - return SharedString(mapIt->first.pData, mapIt->second.pData); + mapIt->second = mapIt2->first.str; + return SharedString(mapIt->first.str.pData, mapIt->second.pData); } // There is no already existing upper string. // First, update using the iterator, can't do this later because // the iterator will be invalid. mapIt->second = aUpper; - mpImpl->maStrMap.emplace_hint(mapIt2, aUpper, aUpper); + mpImpl->maStrMap.emplace_hint(mapIt2, aUpperWithHash, aUpper); return SharedString(rStr.pData, aUpper.pData); } @@ -92,7 +124,7 @@ void SharedStringPool::purge() auto itEnd = mpImpl->maStrMap.end(); while (it != itEnd) { - rtl_uString* p1 = it->first.pData; + rtl_uString* p1 = it->first.str.pData; rtl_uString* p2 = it->second.pData; if (p1 != p2) { @@ -112,7 +144,7 @@ void SharedStringPool::purge() itEnd = mpImpl->maStrMap.end(); while (it != itEnd) { - rtl_uString* p1 = it->first.pData; + rtl_uString* p1 = it->first.str.pData; rtl_uString* p2 = it->second.pData; if (p1 == p2) { |