[PATCH] Un-QRegExp'ify KGuiItem::plainText()

Maks Orlovich kde-optimize@mail.kde.org
Mon, 27 Jan 2003 11:29:40 -0500


--Boundary-00=_05VN+Ij2qEGLAwB
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Hi.. Currently KGuiItem uses QRegExp-based replacement to get rid of accels. 
That's slow, and drags us down for about 15ms or so of the startup time. 
The attached patch replaces this with a specialized routine.

Pros:
Cuts around 14ms of startup time - timings below.

Cons:
1. Binary size larger (by 429 bytes with gcc-3.2.1 -O2). This can be cut down 
to about 160 or so bytes by const-casting unicode() return on the stripped 
string, and accessing it directly - but see 2.

2. Larger/more complex code..


Timings:

Overhad:
KCounterProf::Cumulative: QString KGuiItem::plainText() const = 0.14
KCounterProf::Cumulative: QString KGuiItem::plainText() const = 0.17
KCounterProf::Cumulative: QString KGuiItem::plainText() const = 0.15
Min: 0.14

Current:
KCounterProf::Cumulative: QString KGuiItem::plainText() const = 16.34
KCounterProf::Cumulative: QString KGuiItem::plainText() const = 15.26
KCounterProf::Cumulative: QString KGuiItem::plainText() const = 16.99
Min: 15.26  No overhead: 15.12

Patch:
KCounterProf::Cumulative: QString KGuiItem::plainText() const = 1.32
KCounterProf::Cumulative: QString KGuiItem::plainText() const = 1.33
KCounterProf::Cumulative: QString KGuiItem::plainText() const = 1.30
Min: 1.30   No overhead: 1.16

Delta: 13.96


Please comment.
-Maksim

--Boundary-00=_05VN+Ij2qEGLAwB
Content-Type: text/x-diff;
  charset="us-ascii";
  name="change.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="change.diff"

Index: kguiitem.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdeui/kguiitem.cpp,v
retrieving revision 1.14
diff -u -3 -p -r1.14 kguiitem.cpp
--- kguiitem.cpp	24 Apr 2002 08:02:36 -0000	1.14
+++ kguiitem.cpp	27 Jan 2003 16:20:13 -0000
@@ -37,7 +37,7 @@ public:
         m_enabled = true;
         m_hasIcon = false;
     }
-    
+
     KGuiItemPrivate( const KGuiItemPrivate &rhs )
     {
         (*this ) = rhs;
@@ -117,11 +117,35 @@ KGuiItem::~KGuiItem() {
 QString KGuiItem::text() const {
     return d->m_text;
 }
+
+
 QString KGuiItem::plainText() const {
-  QString stripped( d->m_text );
-  stripped.replace( QRegExp( "&(?!&)" ), QString::null );
+    int len = d->m_text.length();
+
+    if (len == 0)
+        return d->m_text;
+
+    //Can assume len >= 1 from now on.
+    QString stripped;
+
+    int resultLength = 0;
+    stripped.setLength(len);
+
+    const QChar* data    = d->m_text.unicode();
+    for (int pos = 0; pos < len - 1; pos++)
+    {
+        //Cut out & unless it's followed by another &
+        //The +1 is safe as we go upto 2nd to last character only.
+        if (data[pos] != '&' || data[pos+1] == '&')
+            stripped[resultLength++] = data[pos];
+    }
+
+    //Always copy the last char - it can't be a start of an accel.
+    //There is guaranteed to be one due to the !empty check
+    stripped[resultLength++] = data[len-1];
+    stripped.truncate(resultLength);
 
-  return stripped;
+    return stripped;
 }
 
 QIconSet KGuiItem::iconSet( KIcon::Group group, int size, KInstance* instance ) const

--Boundary-00=_05VN+Ij2qEGLAwB--