[prev in list] [next in list] [prev in thread] [next in thread] 

List:       koffice-devel
Subject:    kword rendering speed: QTextFormatCollection
From:       Jos van den Oever <Jos.van.den.Oever () kogmbh ! com>
Date:       2009-09-25 23:52:06
Message-ID: 200909260152.06879.Jos.van.den.Oever () kogmbh ! com
[Download RAW message or body]

Hi all,

I looked into KWord loading speed today and found an interesting bottleneck. 
While loading the ODF 1.2 draft [1], 23% of CPU time was spent in 
QTextFormatCollection::indexForFormat, which itself called 
QTextFormat::operator==(QTextFormat const&) a lot.

The reason for this is inefficient looking up of QTextFormat indexes in 
QTextFormatCollection. I have attached a patch for Qt that fixes the problem. 
Unfortunately the patch is binary incompatible in the strictest sense. A 
variable
  QSet<uint> hashes;
is changed to
  QMultiHash<uint,int> hashes;

Both types are 8 bytes and not used outside of QTextFormatCollection.
This patch speeds up rendering large documents.

I measured rendering by calling "time kword OpenDocument-v1.2-part1-cd03.odt" 
and pressing the close button when i saw the white of the page. Here are the 
rendering times in seconds:

without patch
9.14
11.19
10.44
8.08
8.22
10.93
------
9.67 +- 1.37

with patch
7.36
7.4
9.7
6.97
7.23
6.99
-----
7.61 +- 1.04

So an average improvement of 2 seconds. Not bad for a (long) performance day.

Cheers,
Jos

-- 
Jos van den Oever, software architect
+49 391 25 19 15 53
http://kogmbh.com/legal/

["qtextformatpatch" (text/x-patch)]

diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index de6d10d..06ceb9c 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -257,13 +257,15 @@ private:
     friend QDataStream &operator>>(QDataStream &, QTextFormat &);
 };
 
+int hash(float d) { return *(int*)&d; }
+
 static uint variantHash(const QVariant &variant)
 {
     switch (variant.type()) {
     case QVariant::Invalid: return 0;
-    case QVariant::Bool: return variant.toBool();
-    case QVariant::Int: return variant.toInt();
-    case QVariant::Double: return static_cast<int>(variant.toDouble());
+    case QVariant::Bool: return (QVariant::Bool << 4) + variant.toBool();
+    case QVariant::Int: return (QVariant::Int << 4) + variant.toInt();
+    case QVariant::Double: return hash(variant.toDouble());
     case QVariant::String: return qHash(variant.toString());
     case QVariant::Color: return qHash(qvariant_cast<QColor>(variant).rgb());
     default: break;
@@ -2982,12 +2984,12 @@ QTextFormatCollection::~QTextFormatCollection()
 
 int QTextFormatCollection::indexForFormat(const QTextFormat &format)
 {
-    uint hash = format.d ? format.d->hash() : 0;
+    uint hash = (format.d ? format.d->hash() : 0) + format.format_type;
     if (hashes.contains(hash)) {
-        for (int i = 0; i < formats.size(); ++i) {
-            if (formats.at(i) == format)
-                return i;
-        }
+    foreach (int i, hashes.values(hash)) {
+        if (formats.count() > i && formats.at(i) == format)
+            return i;
+    }
     }
     int idx = formats.size();
     formats.append(format);
@@ -2997,17 +3000,18 @@ int QTextFormatCollection::indexForFormat(const QTextFormat &format)
         f.d = new QTextFormatPrivate;
     f.d->resolveFont(defaultFnt);
 
-    hashes.insert(hash);
+    hashes.insert(hash, idx);
     return idx;
 }
 
 bool QTextFormatCollection::hasFormatCached(const QTextFormat &format) const
 {
-    uint hash = format.d ? format.d->hash() : 0;
+    uint hash = (format.d ? format.d->hash() : 0) + format.format_type;
     if (hashes.contains(hash)) {
-        for (int i = 0; i < formats.size(); ++i)
-            if (formats.at(i) == format)
-                return true;
+    foreach (int i, hashes.values(hash)) {
+        if (formats.count() > i && formats.at(i) == format)
+            return true;
+    }
     }
     return false;
 }
diff --git a/src/gui/text/qtextformat_p.h b/src/gui/text/qtextformat_p.h
index 40e73ab..1dcd47c 100644
--- a/src/gui/text/qtextformat_p.h
+++ b/src/gui/text/qtextformat_p.h
@@ -55,7 +55,7 @@
 
 #include "QtGui/qtextformat.h"
 #include "QtCore/qvector.h"
-#include "QtCore/qset.h"
+#include "QtCore/qhash.h"
 
 QT_BEGIN_NAMESPACE
 
@@ -97,7 +97,7 @@ public:
 
     FormatVector formats;
     QVector<qint32> objFormats;
-    QSet<uint> hashes;
+    QMultiHash<uint,int> hashes;
 
     inline QFont defaultFont() const { return defaultFnt; }
     void setDefaultFont(const QFont &f);


_______________________________________________
koffice-devel mailing list
koffice-devel@kde.org
https://mail.kde.org/mailman/listinfo/koffice-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic