From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: no-spam@cua.dk (Kim F. Storm) Newsgroups: gmane.emacs.devel Subject: Fix for slow process output processing (please test). Date: 16 Dec 2003 02:21:35 +0100 Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1071534268 332 80.91.224.253 (16 Dec 2003 00:24:28 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Tue, 16 Dec 2003 00:24:28 +0000 (UTC) Original-X-From: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Tue Dec 16 01:24:24 2003 Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1AW30i-00088y-00 for ; Tue, 16 Dec 2003 01:24:24 +0100 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.35 #1 (Debian)) id 1AW30i-0001NF-00 for ; Tue, 16 Dec 2003 01:24:24 +0100 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.24) id 1AW3xs-0001Pu-Jt for emacs-devel@quimby.gnus.org; Mon, 15 Dec 2003 20:25:32 -0500 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.24) id 1AW3xX-0001Ci-Pl for emacs-devel@gnu.org; Mon, 15 Dec 2003 20:25:11 -0500 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.24) id 1AW3ws-0008So-59 for emacs-devel@gnu.org; Mon, 15 Dec 2003 20:25:01 -0500 Original-Received: from [195.41.46.237] (helo=pfepc.post.tele.dk) by monty-python.gnu.org with esmtp (Exim 4.24) id 1AW3wC-0007Yg-Tj for emacs-devel@gnu.org; Mon, 15 Dec 2003 20:23:49 -0500 Original-Received: from kfs-l.imdomain.dk.cua.dk (0x503e2644.bynxx3.adsl-dhcp.tele.dk [80.62.38.68]) by pfepc.post.tele.dk (Postfix) with SMTP id 79914262941 for ; Tue, 16 Dec 2003 01:22:15 +0100 (CET) Original-To: emacs-devel@gnu.org Original-Lines: 245 User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3.50 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.2 Precedence: list List-Id: Emacs development discussions. List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:18703 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:18703 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;