Bug 128690

Summary: Dynamic word wrap makes text input slow
Product: [Applications] kate Reporter: Martin Konopka <martin.konopka>
Component: generalAssignee: KWrite Developers <kwrite-bugs-null>
Status: RESOLVED FIXED    
Severity: normal CC: vincenzo_ml
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Martin Konopka 2006-06-05 15:38:13 UTC
Version:           2.5.2 (using KDE 3.5.2, Kubuntu Package 4:3.5.2-0ubuntu18 dapper)
Compiler:          Target: i486-linux-gnu
OS:                Linux (i686) release 2.6.15-23-686

When dynamic word wrap is turned on in Kate, text input gets extremely slow when the paragraph gets longer. I can virtually see ever character appear after I finish writing. When I turn dynamic word wrap off, editing the same paragraph is fast again. Text input is also fast again when I hit return and start a new paragraph. This also happens in Kile.

Thanks for any help!

Martin
Comment 1 Leo Savernik 2006-06-06 15:57:03 UTC
Am Montag, 5. Juni 2006 15:38 schrieb Martin Konopka:
> When dynamic word wrap is turned on in Kate, text input gets extremely slow
> when the paragraph gets longer


I can confirm that. In KDE 3.5.3 dynamic word wrap causes kate's rendering and 
text input to degrade severely. I've noticed it using the LaTeX-highlighter 
as LaTeX-documents can get quite long dynamically wrapped paragraphs.
Comment 2 Leo Savernik 2006-06-07 19:34:15 UTC
I investigated the issue and found the culprit to be within

void KateRenderer::paintTextLine(QPainter& paint, const KateLineRange* range, 
in


Here, only for the first visual line the painting of individual characters is 
coalesced (therefore, it's fast if dynamic word wrap is switched off as there 
is only one visible line).

For all other visual lines, QPainter::drawText (located at // Here's where the 
money is...) is called individually for *every single* character, thus 
killing performance.

I don't know what's causing this, but it may give you devs some hint.
Comment 3 Leo Savernik 2006-06-09 19:09:12 UTC
SVN commit 549739 by savernik:

- Fixed slow repaints of dynamically wrapped lines.
- Also optimised calculation of KateTextLine::cursorX.

Reviewed by Dominik Haumann.

BUG: 128690


 M  +3 -2      katerenderer.cpp  
 M  +3 -2      katetextline.cpp  


--- branches/KDE/3.5/kdelibs/kate/part/katerenderer.cpp #549738:549739
@@ -425,7 +425,8 @@
     while (curCol - startcol < len)
     {
       // make sure curPos is updated correctly.
-      Q_ASSERT(curPos == textLine->cursorX(curCol, m_tabWidth));
+      // ### if uncommented, causes an O(n^2) behaviour
+      //Q_ASSERT(curPos == textLine->cursorX(curCol, m_tabWidth));
 
       QChar curChar = textLine->string()[curCol];
       // Decide if this character is a tab - we treat the spacing differently
@@ -497,7 +498,7 @@
           || (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == KateTextCursor(line, nextCol))
 
           // it is the end of the line OR
-          || (curCol >= len - 1)
+          || (curCol - startcol >= len - 1)
 
           // the rest of the line is trailing whitespace OR
           || (curCol + 1 >= trailingWhitespaceColumn)
--- branches/KDE/3.5/kdelibs/kate/part/katetextline.cpp #549738:549739
@@ -209,9 +209,10 @@
 {
   uint x = 0;
 
-  for ( uint z = 0; z < kMin (pos, m_text.length()); z++)
+  const uint n = kMin (pos, m_text.length());
+  for ( uint z = 0; z < n; z++)
   {
-    if (m_text[z] == QChar('\t'))
+    if (m_text.unicode()[z] == QChar('\t'))
       x += tabChars - (x % tabChars);
     else
       x++;
Comment 4 Dominik Haumann 2006-06-10 11:26:01 UTC
This is btw a dupe of bug #64569
Comment 5 Andreas Kling 2006-06-10 12:11:06 UTC
SVN commit 549908 by kling:

Further optimization of KateTextLine::cursorX()
callgrind reports "inclusive cost" down from 25% to 0.3% when scrolling through planetkde.org HTML.

CCBUG: 128690


 M  +3 -1      katetextline.cpp  


--- branches/KDE/3.5/kdelibs/kate/part/katetextline.cpp #549907:549908
@@ -210,9 +210,11 @@
   uint x = 0;
 
   const uint n = kMin (pos, m_text.length());
+  const QChar *unicode = m_text.unicode();
+  const QChar tab('\t');
   for ( uint z = 0; z < n; z++)
   {
-    if (m_text.unicode()[z] == QChar('\t'))
+    if (unicode[z] == tab)
       x += tabChars - (x % tabChars);
     else
       x++;
Comment 6 Andreas Kling 2006-06-11 09:55:13 UTC
SVN commit 550220 by kling:

Don't memset() from the current item to end-of-line when setting highlight attributes.
End-of-item will do just fine, and now we get 31kB worth of memset() instead of 260MB
when inserting one character in the osnews.com HTML source.

CCBUG: 128690


 M  +1 -1      katehighlight.cpp  


--- branches/KDE/3.5/kdelibs/kate/part/katehighlight.cpp #550219:550220
@@ -1522,7 +1522,7 @@
         // even set attributes ;)
         memset ( textLine->attributes()+offset
                , item->onlyConsume ? context->attr : item->attr
-               , len-offset);
+               , offset2-offset);
 
         offset = offset2;
         lastChar = text[offset-1];
Comment 7 Leo Savernik 2006-06-11 15:03:03 UTC
Am Samstag, 10. Juni 2006 11:26 schrieb Dominik Haumann:
> This is btw a dupe of bug #64569


I don't think so. bug 64569 is about slow syntax hl irrespective of wrapping, 
this one about slow painting of dynamically wrapped lines (hl'd or not).
Comment 8 Dominik Haumann 2006-06-11 15:07:10 UTC
Ok, you are right, the symptoms are quite the same, though :)
Comment 9 Dominik Haumann 2006-06-26 12:31:47 UTC
just for info: fix already in trunk, in slightly different version ;)
Comment 10 Vincenzo Ciancia 2009-04-07 13:07:05 UTC
This bug is still present in 

kile 
Version 2.0.81
Using KDE 4.2.2 (KDE 4.2.2)

If I keep dynamic word wrap enabled, cursor movement, editing and anything related is unbearably slow. If I disable dynamic word wrap everything is normal again. Notice that there are two places where I can enable or disable seemingly two different notions of "dynamic word wrapping": in the main menu (view) or in the configuration, under the editor settings. The latter has no effect, only the former works and makes things slow. 

Resorting to static word wrap for now, but it has drawbacks.