emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Fix for slow process output processing (please test).


From: Kim F. Storm
Subject: Fix for slow process output processing (please test).
Date: 16 Dec 2003 02:21:35 +0100
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3.50

David Kastrup and others have reported very slow processing of process
output, particularly with the Linux kernel's scheduler giving emacs
too much attention while starving the processing producing the output.

Below is a patch which introduces a small delay on reading output from
such processes, without using global delays in processing other events
(this is done by temporarily removing the process' file descriptor from
the call to select and use a short timeout on the select instead.

I have not yet tested this extensively, but would like some feedback
on whether it actually does have the intended positive effect on the
processing of process output.  Could people who have experienced
these problems pls. try the patch and give me feedback.

The patch is against CVS emacs at the time of "server shutdown".

++kfs


*** process.h.~1.24.~   2003-09-01 17:45:56.000000000 +0200
--- process.h   2003-12-16 00:39:22.000000000 +0100
***************
*** 101,106 ****
--- 101,115 ----
         generated, and can be changed by the function
         `set-process-fileter-multibyte'. */
      Lisp_Object filter_multibyte;
+     /* Hysteresis to try to read process output in larger blocks.
+        On some systems, e.g. the Linux kernel, emacs is seen as 
+        an interactive app also when reading process output, meaning
+        that process output can be read in as little as 1 byte at a
+        time.  Value is micro-seconds to delay reading output from
+        this process.  Range is 0 .. 50000.  */
+     Lisp_Object read_output_delay;
+     /* Skip reading this process on next read.  */
+     Lisp_Object read_output_skip;
  };
  
  /* Every field in the preceding structure except for the first two

*** process.c.~1.417.~  2003-11-16 22:25:47.000000000 +0100
--- process.c   2003-12-16 02:00:47.000000000 +0100
***************
*** 260,265 ****
--- 260,282 ----
  #undef DATAGRAM_SOCKETS
  #endif
  
+ #ifdef EMACS_HAS_USECS
+ 
+ #define READ_OUTPUT_DELAY_INCREMENT 10000
+ #define READ_OUTPUT_DELAY_MAX       (READ_OUTPUT_DELAY_INCREMENT * 5)
+ #define READ_OUTPUT_DELAY_MAX_MAX   (READ_OUTPUT_DELAY_INCREMENT * 7)
+ 
+ /* Number of processes which might be delayed.  */
+ 
+ static int process_output_delay_count;
+ 
+ /* Non-zero if any process has non-nil process_output_skip.  */
+ 
+ static int process_output_skip;
+ #else
+ #define process_output_delay_count 0
+ #endif
+ 
  
  #include "sysselect.h"
  
***************
*** 573,578 ****
--- 590,600 ----
    p->status = Qrun;
    p->mark = Fmake_marker ();
  
+ #ifdef READ_OUTPUT_DELAY_INCREMENT
+   XSETFASTINT (p->read_output_delay, 0);
+   p->read_output_skip = Qnil;
+ #endif
+ 
    /* If name is already in use, modify it until it is unused.  */
  
    name1 = name;
***************
*** 3588,3593 ****
--- 3610,3625 ----
    inchannel = XINT (p->infd);
    outchannel = XINT (p->outfd);
  
+ #ifdef READ_OUTPUT_DELAY_INCREMENT
+   if (XINT (p->read_output_delay) > 0)
+     {
+       if (--process_output_delay_count < 0)
+       process_output_delay_count = 0;
+       XSETINT (p->read_output_delay, 0);
+       p->read_output_skip = Qnil;
+     }
+ #endif
+       
    if (inchannel >= 0)
      {
        /* Beware SIGCHLD hereabouts. */
***************
*** 3973,3979 ****
    register int channel, nfds;
    static SELECT_TYPE Available;
    static SELECT_TYPE Connecting;
!   int check_connect, no_avail;
    int xerrno;
    Lisp_Object proc;
    EMACS_TIME timeout, end_time;
--- 4005,4011 ----
    register int channel, nfds;
    static SELECT_TYPE Available;
    static SELECT_TYPE Connecting;
!   int check_connect, check_delay, no_avail;
    int xerrno;
    Lisp_Object proc;
    EMACS_TIME timeout, end_time;
***************
*** 4202,4208 ****
        if (!NILP (wait_for_cell))
        {
          Available = non_process_wait_mask;
!         check_connect = 0;
        }
        else
        {
--- 4234,4240 ----
        if (!NILP (wait_for_cell))
        {
          Available = non_process_wait_mask;
!         check_connect = check_delay = 0;
        }
        else
        {
***************
*** 4211,4216 ****
--- 4243,4249 ----
          else
            Available = input_wait_mask;
          check_connect = (num_pending_connects > 0);
+         check_delay = process_output_delay_count;
        }
  
        /* If frame size has changed or the window is newly mapped,
***************
*** 4236,4241 ****
--- 4269,4302 ----
        {
          if (check_connect)
            Connecting = connect_wait_mask;
+ 
+ #ifdef READ_OUTPUT_DELAY_INCREMENT
+         if (process_output_skip && check_delay > 0)
+           {
+             int usecs = EMACS_USECS (timeout);
+             if (EMACS_SECS (timeout) > 0 || usecs > READ_OUTPUT_DELAY_MAX)
+               usecs = READ_OUTPUT_DELAY_MAX;
+             for (channel = 0; check_delay > 0 && channel <= max_process_desc; 
channel++)
+               {
+                 proc = chan_process[channel];
+                 if (NILP (proc))
+                   continue;
+                 if (XPROCESS (proc)->read_output_delay > 0)
+                   {
+                     check_delay--;
+                     if (NILP (XPROCESS (proc)->read_output_skip))
+                       continue;
+                     FD_CLR (channel, &Available);
+                     XPROCESS (proc)->read_output_skip = Qnil;
+                     if (XINT (XPROCESS (proc)->read_output_delay) < usecs)
+                       usecs = XINT (XPROCESS (proc)->read_output_delay);
+                   }
+               }
+             EMACS_SET_SECS_USECS (timeout, 0, usecs);
+             process_output_skip = 0;
+           }
+ #endif
+ 
          nfds = select (max (max_process_desc, max_keyboard_desc) + 1,
                         &Available,
                         (check_connect ? &Connecting : (SELECT_TYPE *)0),
***************
*** 4689,4695 ****
    else
  #endif
    if (proc_buffered_char[channel] < 0)
!     nbytes = emacs_read (channel, chars + carryover, readmax - carryover);
    else
      {
        chars[carryover] = proc_buffered_char[channel];
--- 4750,4785 ----
    else
  #endif
    if (proc_buffered_char[channel] < 0)
!     {
!       nbytes = emacs_read (channel, chars + carryover, readmax - carryover);
! #ifdef READ_OUTPUT_DELAY_INCREMENT
!       if (!NETCONN1_P (p))
!       {
!         int delay = XINT (p->read_output_delay);
!         if (nbytes < readmax - carryover)
!           {
!             if (delay < READ_OUTPUT_DELAY_MAX_MAX)
!               {
!                 if (delay == 0)
!                   process_output_delay_count++;
!                 delay += READ_OUTPUT_DELAY_INCREMENT;
!               }
!           }
!         else if (delay > 0)
!           {
!             delay -= READ_OUTPUT_DELAY_INCREMENT;
!             if (delay == 0)
!               process_output_delay_count--;
!           }
!         XSETINT (p->read_output_delay, delay);
!         if (delay)
!           {
!             p->read_output_skip = Qt;
!             process_output_skip = 1;
!           }
!       }
! #endif
!     }
    else
      {
        chars[carryover] = proc_buffered_char[channel];
***************
*** 6503,6508 ****
--- 6593,6603 ----
    FD_ZERO (&non_process_wait_mask);
    max_process_desc = 0;
  
+ #ifdef READ_OUTPUT_DELAY_INCREMENT
+   process_output_delay_count = 0;
+   process_output_skip = 0;
+ #endif
+ 
    FD_SET (0, &input_wait_mask);
  
    Vprocess_alist = Qnil;







reply via email to

[Prev in Thread] Current Thread [Next in Thread]