summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2022-04-06 19:28:07 +0200
committerLuboš Luňák <l.lunak@collabora.com>2022-04-08 21:28:15 +0200
commit94c2fb28d76c9c37849412a66b31d6861bce3155 (patch)
treea29aae0728d3ee744cf02ee5cc3a831154b092c2
parent1b593dbc62dc2ceebc3f8be30d7221c916098f6d (diff)
faster hashing of very long strings in SalLayoutGlyphsCache
tdf#147284 being a (pathological) testcase. Change-Id: I08d8dffb40193b461555bed818c040761e8d575b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132669 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r--vcl/inc/TextLayoutCache.hxx32
-rw-r--r--vcl/source/gdi/CommonSalLayout.cxx30
-rw-r--r--vcl/source/gdi/impglyphitem.cxx6
3 files changed, 37 insertions, 31 deletions
diff --git a/vcl/inc/TextLayoutCache.hxx b/vcl/inc/TextLayoutCache.hxx
index 0ce0c19d8278..ecb85ea7043d 100644
--- a/vcl/inc/TextLayoutCache.hxx
+++ b/vcl/inc/TextLayoutCache.hxx
@@ -20,6 +20,8 @@
#pragma once
#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <o3tl/hash_combine.hxx>
#include <vcl/dllapi.h>
@@ -48,6 +50,36 @@ public:
std::vector<vcl::text::Run> runs;
TextLayoutCache(sal_Unicode const* pStr, sal_Int32 const nEnd);
};
+
+struct FirstCharsStringHash
+{
+ size_t operator()(const OUString& str) const
+ {
+ // Strings passed to GenericSalLayout::CreateTextLayoutCache() may be very long,
+ // and computing an entire hash could almost negate the gain of hashing. Hash just first
+ // characters, that should be good enough.
+ size_t hash
+ = rtl_ustr_hashCode_WithLength(str.getStr(), std::min<size_t>(100, str.getLength()));
+ o3tl::hash_combine(hash, str.getLength());
+ return hash;
+ }
+};
+
+struct FastStringCompareEqual
+{
+ bool operator()(const OUString& str1, const OUString& str2) const
+ {
+ // Strings passed to GenericSalLayout::CreateTextLayoutCache() may be very long,
+ // and OUString operator == compares backwards and using hard-written code, while
+ // memcmp() compares much faster.
+ if (str1.getLength() != str2.getLength())
+ return false;
+ if (str1.getStr() == str2.getStr())
+ return true;
+ return memcmp(str1.getStr(), str2.getStr(), str1.getLength() * sizeof(str1.getStr()[0]))
+ == 0;
+ }
+};
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 8dee28727997..2c8a4db8398f 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -154,40 +154,12 @@ namespace {
return VerticalOrientation(nRet);
}
-struct FirstCharsStringHash
-{
- size_t operator()( const OUString& str ) const
- {
- // Strings passed to GenericSalLayout::CreateTextLayoutCache() may be very long,
- // and computing an entire hash could almost negate the gain of hashing. Hash just first
- // characters, that should be good enough.
- size_t hash = rtl_ustr_hashCode_WithLength( str.getStr(), std::min<size_t>( 100, str.getLength()));
- o3tl::hash_combine(hash, str.getLength());
- return hash;
- }
-};
-
-struct ForwardStringCompareEqual
-{
- bool operator()( const OUString& str1, const OUString& str2 ) const
- {
- // Strings passed to GenericSalLayout::CreateTextLayoutCache() may be very long,
- // and OUString operator == compares backwards, which is inefficient for very long
- // strings (bad memory prefetch).
- if( str1.getLength() != str2.getLength())
- return false;
- if( str1.getStr() == str2.getStr())
- return true;
- return memcmp( str1.getStr(), str2.getStr(), str1.getLength() * sizeof( str1.getStr()[ 0 ] )) == 0;
- }
-};
-
} // namespace
std::shared_ptr<const vcl::text::TextLayoutCache> GenericSalLayout::CreateTextLayoutCache(OUString const& rString)
{
typedef o3tl::lru_map<OUString, std::shared_ptr<const vcl::text::TextLayoutCache>,
- FirstCharsStringHash, ForwardStringCompareEqual> Cache;
+ vcl::text::FirstCharsStringHash, vcl::text::FastStringCompareEqual> Cache;
static vcl::DeleteOnDeinit< Cache > cache( 1000 );
if( Cache* map = cache.get())
{
diff --git a/vcl/source/gdi/impglyphitem.cxx b/vcl/source/gdi/impglyphitem.cxx
index eaf8cf5c8453..d320d27dad88 100644
--- a/vcl/source/gdi/impglyphitem.cxx
+++ b/vcl/source/gdi/impglyphitem.cxx
@@ -21,6 +21,7 @@
#include <vcl/glyphitemcache.hxx>
#include <vcl/vcllayout.hxx>
#include <tools/stream.hxx>
+#include <TextLayoutCache.hxx>
SalLayoutGlyphs::SalLayoutGlyphs() {}
@@ -146,7 +147,7 @@ SalLayoutGlyphsCache::CachedGlyphsKey::CachedGlyphsKey(const VclPtr<const Output
SvMemoryStream stream;
WriteFont(stream, outputDevice->GetFont());
o3tl::hash_combine(hashValue, static_cast<const char*>(stream.GetData()), stream.GetSize());
- o3tl::hash_combine(hashValue, text);
+ o3tl::hash_combine(hashValue, vcl::text::FirstCharsStringHash()(text));
o3tl::hash_combine(hashValue, index);
o3tl::hash_combine(hashValue, len);
o3tl::hash_combine(hashValue, logicPos.X());
@@ -158,7 +159,8 @@ inline bool SalLayoutGlyphsCache::CachedGlyphsKey::operator==(const CachedGlyphs
{
return hashValue == other.hashValue && outputDevice == other.outputDevice
&& index == other.index && len == other.len && logicPos == other.logicPos
- && logicWidth == other.logicWidth && text == other.text;
+ && logicWidth == other.logicWidth
+ && vcl::text::FastStringCompareEqual()(text, other.text);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */