Konsole scrolling

Waldo Bastian kde-optimize@mail.kde.org
Thu, 20 Feb 2003 15:47:13 +0100


--Boundary-00=_xpOV+k7n96P2HbD
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Thursday 20 February 2003 12:45, Karl Vogel wrote:
> On 20 Feb 2003, you wrote in kde.kde-optimize:
> > Which scroll-speed are we interested in? Scrollbar scrolling or
> > scrolling caused by issuing "find /"?
>
> The scrollbar kind.. dragging the scrollbar soaks up all CPU time and is
> really laggy.

Hm.

> > You can improve the latter by fiddling with the refresh rate.
> > Refreshes are slightly delayed and forced after every N bytes/packets
> > of data. Not exactly, but something like that. See TEmulation.cpp and
> > how showBulk() gets called.
>
> Yups.. I understand how the bulk operation works. It's this that makes the
> scrolling of shell output acceptable (delaying updates with the bulk timer
> or until a NewLine is seen). -- correct me if I'm wrong
>
> But even for the NewLine case, using a scroll() would be faster and more
> importantly, less of a cpuhog.

That depends, if between two updates an entire screen has scrolled by, there 
is no gain.

> The problem is that the knowledge about how to update the screen is thrown
> away and instead an entire screen diff update is done, whereas we KNOW only
> the last line really changed. (or in case of scrollbar scrolling, we know
> which lines don't need repainting)

True. I doubt however that this will really gain you so much. You either a) 
scroll a little in which case you don't care much about the CPU, because it 
is only a small spike. Or b) you scroll a lot, but then you are most likely 
scrolling more than one page, so you will not gain anything.

There is also c) You scroll a lot and do updates for every few lines. That's 
stupid :) but might very well be what konsole is doing.

The following patch makes some changes to the bulk algorithm and uses it for 
scrollbar related updates as well. It guarantees a refresh rate between 100Hz 
and 20Hz, assuming your CPU is fast enough for the latter :-}

Does this help? bitblt-based scrolling could still be done on top of this, but 
I'm afraid it will be really hairy to get it right. The current approach with 
the images was specifically choosen to get rid of the hairy bits :)

Cheers,
Waldo
-- 
bastian@kde.org -=|[ SuSE, The Linux Desktop Experts ]|=- bastian@suse.com

--Boundary-00=_xpOV+k7n96P2HbD
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="konsole_scroll.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="konsole_scroll.diff"

Index: TEmulation.cpp
===================================================================
RCS file: /home/kde/kdebase/konsole/konsole/TEmulation.cpp,v
retrieving revision 1.48
diff -u -r1.48 TEmulation.cpp
--- TEmulation.cpp	5 Jan 2003 20:01:06 -0000	1.48
+++ TEmulation.cpp	20 Feb 2003 14:37:01 -0000
@@ -49,15 +49,11 @@
    As soon as no more data arrive for `BULK_TIMEOUT' milliseconds, we trigger
    refresh. This rule suits both bulk display operation as done by curses as
    well as individual characters typed.
-   (BULK_TIMEOUT < 1000 / max characters received from keyboard per second).
 
-   Additionally, we trigger refreshing by newlines comming in to make visual
-   snapshots of lists as produced by `cat', `ls' and likely programs, thereby
-   producing the illusion of a permanent and immediate display operation.
-
-   As a sort of catch-all needed for cases where none of the above
-   conditions catch, the screen refresh is also triggered by a count
-   of incoming bulks (`bulk_incnt').
+   We start also a second time which is never restarted. If repeatedly
+   restarting of the first timer could delay continous output indefinitly,
+   the second timer guarantees that the output is refreshed with at least
+   a fixed rate.
 */
 
 /* FIXME
@@ -101,8 +97,6 @@
   codec(0),
   decoder(0),
   keytrans(0),
-  bulk_nlcnt(0),
-  bulk_incnt(0),
   m_findPos(-1)
 {
 
@@ -110,7 +104,8 @@
   screen[1] = new TEScreen(gui->Lines(),gui->Columns());
   scr = screen[0];
 
-  QObject::connect(&bulk_timer, SIGNAL(timeout()), this, SLOT(showBulk()) );
+  QObject::connect(&bulk_timer1, SIGNAL(timeout()), this, SLOT(showBulk()) );
+  QObject::connect(&bulk_timer2, SIGNAL(timeout()), this, SLOT(showBulk()) );
   connectGUI();
   setKeymap(0); // Default keymap
 }
@@ -179,7 +174,6 @@
   delete screen[0];
   delete screen[1];
   delete decoder;
-  bulk_timer.stop();
 }
 
 /*! change between primary and alternate screen
@@ -306,7 +300,6 @@
   emit notifySessionState(NOTIFYACTIVITY);
 
   bulkStart();
-  bulk_incnt += 1;
   for (int i = 0; i < len; i++)
   {
     QString result = decoder->toUnicode(&s[i],1);
@@ -423,7 +416,8 @@
 
 // Refreshing -------------------------------------------------------------- --
 
-#define BULK_TIMEOUT 10
+#define BULK_TIMEOUT1 10
+#define BULK_TIMEOUT2 50
 
 /*!
    called when \n comes in. Evtl. triggers showBulk at endBulk
@@ -431,8 +425,6 @@
 
 void TEmulation::bulkNewline()
 {
-  bulk_nlcnt += 1;
-  bulk_incnt = 0;  // reset bulk counter since `nl' rule applies
 }
 
 /*!
@@ -440,8 +432,9 @@
 
 void TEmulation::showBulk()
 {
-  bulk_nlcnt = 0;                       // reset bulk newline counter
-  bulk_incnt = 0;                       // reset bulk counter
+  bulk_timer1.stop();
+  bulk_timer2.stop();
+
   if (connected)
   {
     ca* image = scr->getCookedImage();    // get the image
@@ -460,15 +453,13 @@
 
 void TEmulation::bulkStart()
 {
-  if (bulk_timer.isActive()) bulk_timer.stop();
+   bulk_timer1.start(BULK_TIMEOUT1,true);
+   if (!bulk_timer2.isActive())
+      bulk_timer2.start(BULK_TIMEOUT2, true);
 }
 
 void TEmulation::bulkEnd()
 {
-  if ( bulk_nlcnt > gui->Lines() || bulk_incnt > 20 )
-    showBulk();                         // resets bulk_??cnt to 0, too.
-  else
-    bulk_timer.start(BULK_TIMEOUT,true);
 }
 
 void TEmulation::setConnect(bool c)
@@ -512,7 +503,8 @@
 {
   if (!connected) return;
   scr->setHistCursor(cursor);
-  showBulk();
+
+  bulkStart();
 }
 
 void TEmulation::setColumns(int columns)
Index: TEmulation.h
===================================================================
RCS file: /home/kde/kdebase/konsole/konsole/TEmulation.h,v
retrieving revision 1.28
diff -u -r1.28 TEmulation.h
--- TEmulation.h	28 Nov 2002 15:35:28 -0000	1.28
+++ TEmulation.h	20 Feb 2003 14:37:01 -0000
@@ -122,9 +122,8 @@
 
 private:
 
-  QTimer bulk_timer;
-  int    bulk_nlcnt;   // bulk newline counter
-  int    bulk_incnt;   // bulk counter
+  QTimer bulk_timer1;
+  QTimer bulk_timer2;
   
   int    m_findPos;
 };

--Boundary-00=_xpOV+k7n96P2HbD--