aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorKim F. Storm2004-01-01 23:34:14 +0000
committerKim F. Storm2004-01-01 23:34:14 +0000
commit2d942bfadfd794e71202b92dd6e6928c70bbfcb0 (patch)
tree16467bcced3fbbf3685b00b4618c44df8ccc3d6c /src/process.c
parent2ba4be11b79b7cc0a7485240cabd7d91f209fb94 (diff)
downloademacs-2d942bfadfd794e71202b92dd6e6928c70bbfcb0.tar.gz
emacs-2d942bfadfd794e71202b92dd6e6928c70bbfcb0.zip
(ADAPTIVE_READ_BUFFERING): New conditional.
(READ_OUTPUT_DELAY_INCREMENT, READ_OUTPUT_DELAY_MAX) (READ_OUTPUT_DELAY_MAX_MAX): New constants. (process_output_delay_count, process_output_skip): New vars. (Vprocess_adaptive_read_buffering): New variable. (make_process): Initialize adaptive read buffering members. (Fstart_process): Set adaptive_read_buffering member. (deactivate_process): Cleanup adaptive read buffering. (wait_reading_process_input): Temporarily omit delayed subprocesses from the set of file descriptors to read from; adjust the select timeout if we skipped any subprocesses. (read_process_output): Increase adaptive read buffering delay if we read less than a full buffer; reduce delay when we read a full buffer. (send_process): Simplify using local Lisp_Process var. Reset adaptive read buffering delay after write. (init_process): Initialize process_output_delay_count and process_output_skip. (syms_of_process): DEFVAR_LISP Vprocess_adaptive_read_buffering.
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c199
1 files changed, 164 insertions, 35 deletions
diff --git a/src/process.c b/src/process.c
index ed0d5fe765b..3cb63de1584 100644
--- a/src/process.c
+++ b/src/process.c
@@ -260,6 +260,33 @@ int update_tick;
260#undef DATAGRAM_SOCKETS 260#undef DATAGRAM_SOCKETS
261#endif 261#endif
262 262
263#if !defined (ADAPTIVE_READ_BUFFERING) && !defined (NO_ADAPTIVE_READ_BUFFERING)
264#ifdef EMACS_HAS_USECS
265#define ADAPTIVE_READ_BUFFERING
266#endif
267#endif
268
269#ifdef ADAPTIVE_READ_BUFFERING
270#define READ_OUTPUT_DELAY_INCREMENT 10000
271#define READ_OUTPUT_DELAY_MAX (READ_OUTPUT_DELAY_INCREMENT * 5)
272#define READ_OUTPUT_DELAY_MAX_MAX (READ_OUTPUT_DELAY_INCREMENT * 7)
273
274/* Number of processes which might be delayed. */
275
276static int process_output_delay_count;
277
278/* Non-zero if any process has non-nil process_output_skip. */
279
280static int process_output_skip;
281
282/* Non-nil means to delay reading process output to improve buffering.
283 A value of t means that delay is reset after each send, any other
284 non-nil value does not reset the delay. */
285static Lisp_Object Vprocess_adaptive_read_buffering;
286#else
287#define process_output_delay_count 0
288#endif
289
263 290
264#include "sysselect.h" 291#include "sysselect.h"
265 292
@@ -573,6 +600,12 @@ make_process (name)
573 p->status = Qrun; 600 p->status = Qrun;
574 p->mark = Fmake_marker (); 601 p->mark = Fmake_marker ();
575 602
603#ifdef ADAPTIVE_READ_BUFFERING
604 p->adaptive_read_buffering = Qnil;
605 XSETFASTINT (p->read_output_delay, 0);
606 p->read_output_skip = Qnil;
607#endif
608
576 /* If name is already in use, modify it until it is unused. */ 609 /* If name is already in use, modify it until it is unused. */
577 610
578 name1 = name; 611 name1 = name;
@@ -1501,6 +1534,10 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
1501 = buffer_defaults.enable_multibyte_characters; 1534 = buffer_defaults.enable_multibyte_characters;
1502 XPROCESS (proc)->command = Flist (nargs - 2, args + 2); 1535 XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
1503 1536
1537#ifdef ADAPTIVE_READ_BUFFERING
1538 XPROCESS (proc)->adaptive_read_buffering = Vprocess_adaptive_read_buffering;
1539#endif
1540
1504 /* Make the process marker point into the process buffer (if any). */ 1541 /* Make the process marker point into the process buffer (if any). */
1505 if (!NILP (buffer)) 1542 if (!NILP (buffer))
1506 set_marker_both (XPROCESS (proc)->mark, buffer, 1543 set_marker_both (XPROCESS (proc)->mark, buffer,
@@ -3588,6 +3625,16 @@ deactivate_process (proc)
3588 inchannel = XINT (p->infd); 3625 inchannel = XINT (p->infd);
3589 outchannel = XINT (p->outfd); 3626 outchannel = XINT (p->outfd);
3590 3627
3628#ifdef ADAPTIVE_READ_BUFFERING
3629 if (XINT (p->read_output_delay) > 0)
3630 {
3631 if (--process_output_delay_count < 0)
3632 process_output_delay_count = 0;
3633 XSETINT (p->read_output_delay, 0);
3634 p->read_output_skip = Qnil;
3635 }
3636#endif
3637
3591 if (inchannel >= 0) 3638 if (inchannel >= 0)
3592 { 3639 {
3593 /* Beware SIGCHLD hereabouts. */ 3640 /* Beware SIGCHLD hereabouts. */
@@ -3973,7 +4020,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
3973 register int channel, nfds; 4020 register int channel, nfds;
3974 static SELECT_TYPE Available; 4021 static SELECT_TYPE Available;
3975 static SELECT_TYPE Connecting; 4022 static SELECT_TYPE Connecting;
3976 int check_connect, no_avail; 4023 int check_connect, check_delay, no_avail;
3977 int xerrno; 4024 int xerrno;
3978 Lisp_Object proc; 4025 Lisp_Object proc;
3979 EMACS_TIME timeout, end_time; 4026 EMACS_TIME timeout, end_time;
@@ -4202,7 +4249,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
4202 if (!NILP (wait_for_cell)) 4249 if (!NILP (wait_for_cell))
4203 { 4250 {
4204 Available = non_process_wait_mask; 4251 Available = non_process_wait_mask;
4205 check_connect = 0; 4252 check_connect = check_delay = 0;
4206 } 4253 }
4207 else 4254 else
4208 { 4255 {
@@ -4211,6 +4258,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
4211 else 4258 else
4212 Available = input_wait_mask; 4259 Available = input_wait_mask;
4213 check_connect = (num_pending_connects > 0); 4260 check_connect = (num_pending_connects > 0);
4261 check_delay = process_output_delay_count;
4214 } 4262 }
4215 4263
4216 /* If frame size has changed or the window is newly mapped, 4264 /* If frame size has changed or the window is newly mapped,
@@ -4236,6 +4284,34 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
4236 { 4284 {
4237 if (check_connect) 4285 if (check_connect)
4238 Connecting = connect_wait_mask; 4286 Connecting = connect_wait_mask;
4287
4288#ifdef ADAPTIVE_READ_BUFFERING
4289 if (process_output_skip && check_delay > 0)
4290 {
4291 int usecs = EMACS_USECS (timeout);
4292 if (EMACS_SECS (timeout) > 0 || usecs > READ_OUTPUT_DELAY_MAX)
4293 usecs = READ_OUTPUT_DELAY_MAX;
4294 for (channel = 0; check_delay > 0 && channel <= max_process_desc; channel++)
4295 {
4296 proc = chan_process[channel];
4297 if (NILP (proc))
4298 continue;
4299 if (XPROCESS (proc)->read_output_delay > 0)
4300 {
4301 check_delay--;
4302 if (NILP (XPROCESS (proc)->read_output_skip))
4303 continue;
4304 FD_CLR (channel, &Available);
4305 XPROCESS (proc)->read_output_skip = Qnil;
4306 if (XINT (XPROCESS (proc)->read_output_delay) < usecs)
4307 usecs = XINT (XPROCESS (proc)->read_output_delay);
4308 }
4309 }
4310 EMACS_SET_SECS_USECS (timeout, 0, usecs);
4311 process_output_skip = 0;
4312 }
4313#endif
4314
4239 nfds = select (max (max_process_desc, max_keyboard_desc) + 1, 4315 nfds = select (max (max_process_desc, max_keyboard_desc) + 1,
4240 &Available, 4316 &Available,
4241 (check_connect ? &Connecting : (SELECT_TYPE *)0), 4317 (check_connect ? &Connecting : (SELECT_TYPE *)0),
@@ -4689,7 +4765,36 @@ read_process_output (proc, channel)
4689 else 4765 else
4690#endif 4766#endif
4691 if (proc_buffered_char[channel] < 0) 4767 if (proc_buffered_char[channel] < 0)
4692 nbytes = emacs_read (channel, chars + carryover, readmax - carryover); 4768 {
4769 nbytes = emacs_read (channel, chars + carryover, readmax - carryover);
4770#ifdef ADAPTIVE_READ_BUFFERING
4771 if (!NILP (p->adaptive_read_buffering))
4772 {
4773 int delay = XINT (p->read_output_delay);
4774 if (nbytes < readmax - carryover)
4775 {
4776 if (delay < READ_OUTPUT_DELAY_MAX_MAX)
4777 {
4778 if (delay == 0)
4779 process_output_delay_count++;
4780 delay += READ_OUTPUT_DELAY_INCREMENT * 2;
4781 }
4782 }
4783 else if (delay > 0)
4784 {
4785 delay -= READ_OUTPUT_DELAY_INCREMENT;
4786 if (delay == 0)
4787 process_output_delay_count--;
4788 }
4789 XSETINT (p->read_output_delay, delay);
4790 if (delay)
4791 {
4792 p->read_output_skip = Qt;
4793 process_output_skip = 1;
4794 }
4795 }
4796#endif
4797 }
4693 else 4798 else
4694 { 4799 {
4695 chars[carryover] = proc_buffered_char[channel]; 4800 chars[carryover] = proc_buffered_char[channel];
@@ -4991,6 +5096,7 @@ send_process (proc, buf, len, object)
4991 volatile Lisp_Object object; 5096 volatile Lisp_Object object;
4992{ 5097{
4993 /* Use volatile to protect variables from being clobbered by longjmp. */ 5098 /* Use volatile to protect variables from being clobbered by longjmp. */
5099 struct Lisp_Process *p = XPROCESS (proc);
4994 int rv; 5100 int rv;
4995 struct coding_system *coding; 5101 struct coding_system *coding;
4996 struct gcpro gcpro1; 5102 struct gcpro gcpro1;
@@ -4998,20 +5104,17 @@ send_process (proc, buf, len, object)
4998 GCPRO1 (object); 5104 GCPRO1 (object);
4999 5105
5000#ifdef VMS 5106#ifdef VMS
5001 struct Lisp_Process *p = XPROCESS (proc);
5002 VMS_PROC_STUFF *vs, *get_vms_process_pointer(); 5107 VMS_PROC_STUFF *vs, *get_vms_process_pointer();
5003#endif /* VMS */ 5108#endif /* VMS */
5004 5109
5005 if (! NILP (XPROCESS (proc)->raw_status_low)) 5110 if (! NILP (p->raw_status_low))
5006 update_status (XPROCESS (proc)); 5111 update_status (p);
5007 if (! EQ (XPROCESS (proc)->status, Qrun)) 5112 if (! EQ (p->status, Qrun))
5008 error ("Process %s not running", 5113 error ("Process %s not running", SDATA (p->name));
5009 SDATA (XPROCESS (proc)->name)); 5114 if (XINT (p->outfd) < 0)
5010 if (XINT (XPROCESS (proc)->outfd) < 0) 5115 error ("Output file descriptor of %s is closed", SDATA (p->name));
5011 error ("Output file descriptor of %s is closed",
5012 SDATA (XPROCESS (proc)->name));
5013 5116
5014 coding = proc_encode_coding_system[XINT (XPROCESS (proc)->outfd)]; 5117 coding = proc_encode_coding_system[XINT (p->outfd)];
5015 Vlast_coding_system_used = coding->symbol; 5118 Vlast_coding_system_used = coding->symbol;
5016 5119
5017 if ((STRINGP (object) && STRING_MULTIBYTE (object)) 5120 if ((STRINGP (object) && STRING_MULTIBYTE (object))
@@ -5019,13 +5122,12 @@ send_process (proc, buf, len, object)
5019 && !NILP (XBUFFER (object)->enable_multibyte_characters)) 5122 && !NILP (XBUFFER (object)->enable_multibyte_characters))
5020 || EQ (object, Qt)) 5123 || EQ (object, Qt))
5021 { 5124 {
5022 if (!EQ (coding->symbol, XPROCESS (proc)->encode_coding_system)) 5125 if (!EQ (coding->symbol, p->encode_coding_system))
5023 /* The coding system for encoding was changed to raw-text 5126 /* The coding system for encoding was changed to raw-text
5024 because we sent a unibyte text previously. Now we are 5127 because we sent a unibyte text previously. Now we are
5025 sending a multibyte text, thus we must encode it by the 5128 sending a multibyte text, thus we must encode it by the
5026 original coding system specified for the current 5129 original coding system specified for the current process. */
5027 process. */ 5130 setup_coding_system (p->encode_coding_system, coding);
5028 setup_coding_system (XPROCESS (proc)->encode_coding_system, coding);
5029 /* src_multibyte should be set to 1 _after_ a call to 5131 /* src_multibyte should be set to 1 _after_ a call to
5030 setup_coding_system, since it resets src_multibyte to 5132 setup_coding_system, since it resets src_multibyte to
5031 zero. */ 5133 zero. */
@@ -5076,15 +5178,15 @@ send_process (proc, buf, len, object)
5076 coding->composing = COMPOSITION_DISABLED; 5178 coding->composing = COMPOSITION_DISABLED;
5077 } 5179 }
5078 5180
5079 if (SBYTES (XPROCESS (proc)->encoding_buf) < require) 5181 if (SBYTES (p->encoding_buf) < require)
5080 XPROCESS (proc)->encoding_buf = make_uninit_string (require); 5182 p->encoding_buf = make_uninit_string (require);
5081 5183
5082 if (from_byte >= 0) 5184 if (from_byte >= 0)
5083 buf = (BUFFERP (object) 5185 buf = (BUFFERP (object)
5084 ? BUF_BYTE_ADDRESS (XBUFFER (object), from_byte) 5186 ? BUF_BYTE_ADDRESS (XBUFFER (object), from_byte)
5085 : SDATA (object) + from_byte); 5187 : SDATA (object) + from_byte);
5086 5188
5087 object = XPROCESS (proc)->encoding_buf; 5189 object = p->encoding_buf;
5088 encode_coding (coding, (char *) buf, SDATA (object), 5190 encode_coding (coding, (char *) buf, SDATA (object),
5089 len, SBYTES (object)); 5191 len, SBYTES (object));
5090 len = coding->produced; 5192 len = coding->produced;
@@ -5102,8 +5204,7 @@ send_process (proc, buf, len, object)
5102 if (pty_max_bytes == 0) 5204 if (pty_max_bytes == 0)
5103 { 5205 {
5104#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON) 5206#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
5105 pty_max_bytes = fpathconf (XFASTINT (XPROCESS (proc)->outfd), 5207 pty_max_bytes = fpathconf (XFASTINT (p->outfd), _PC_MAX_CANON);
5106 _PC_MAX_CANON);
5107 if (pty_max_bytes < 0) 5208 if (pty_max_bytes < 0)
5108 pty_max_bytes = 250; 5209 pty_max_bytes = 250;
5109#else 5210#else
@@ -5126,7 +5227,7 @@ send_process (proc, buf, len, object)
5126 5227
5127 /* Decide how much data we can send in one batch. 5228 /* Decide how much data we can send in one batch.
5128 Long lines need to be split into multiple batches. */ 5229 Long lines need to be split into multiple batches. */
5129 if (!NILP (XPROCESS (proc)->pty_flag)) 5230 if (!NILP (p->pty_flag))
5130 { 5231 {
5131 /* Starting this at zero is always correct when not the first 5232 /* Starting this at zero is always correct when not the first
5132 iteration because the previous iteration ended by sending C-d. 5233 iteration because the previous iteration ended by sending C-d.
@@ -5155,7 +5256,7 @@ send_process (proc, buf, len, object)
5155 /* Send this batch, using one or more write calls. */ 5256 /* Send this batch, using one or more write calls. */
5156 while (this > 0) 5257 while (this > 0)
5157 { 5258 {
5158 int outfd = XINT (XPROCESS (proc)->outfd); 5259 int outfd = XINT (p->outfd);
5159 old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap); 5260 old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
5160#ifdef DATAGRAM_SOCKETS 5261#ifdef DATAGRAM_SOCKETS
5161 if (DATAGRAM_CHAN_P (outfd)) 5262 if (DATAGRAM_CHAN_P (outfd))
@@ -5168,7 +5269,18 @@ send_process (proc, buf, len, object)
5168 } 5269 }
5169 else 5270 else
5170#endif 5271#endif
5171 rv = emacs_write (outfd, (char *) buf, this); 5272 {
5273 rv = emacs_write (outfd, (char *) buf, this);
5274#ifdef ADAPTIVE_READ_BUFFERING
5275 if (XINT (p->read_output_delay) > 0
5276 && EQ (p->adaptive_read_buffering, Qt))
5277 {
5278 XSETFASTINT (p->read_output_delay, 0);
5279 process_output_delay_count--;
5280 p->read_output_skip = Qnil;
5281 }
5282#endif
5283 }
5172 signal (SIGPIPE, old_sigpipe); 5284 signal (SIGPIPE, old_sigpipe);
5173 5285
5174 if (rv < 0) 5286 if (rv < 0)
@@ -5209,8 +5321,7 @@ send_process (proc, buf, len, object)
5209 if (errno == EAGAIN) 5321 if (errno == EAGAIN)
5210 { 5322 {
5211 int flags = FWRITE; 5323 int flags = FWRITE;
5212 ioctl (XINT (XPROCESS (proc)->outfd), TIOCFLUSH, 5324 ioctl (XINT (p->outfd), TIOCFLUSH, &flags);
5213 &flags);
5214 } 5325 }
5215#endif /* BROKEN_PTY_READ_AFTER_EAGAIN */ 5326#endif /* BROKEN_PTY_READ_AFTER_EAGAIN */
5216 5327
@@ -5255,18 +5366,17 @@ send_process (proc, buf, len, object)
5255 { 5366 {
5256#ifndef VMS 5367#ifndef VMS
5257 proc = process_sent_to; 5368 proc = process_sent_to;
5369 p = XPROCESS (proc);
5258#endif 5370#endif
5259 XPROCESS (proc)->raw_status_low = Qnil; 5371 p->raw_status_low = Qnil;
5260 XPROCESS (proc)->raw_status_high = Qnil; 5372 p->raw_status_high = Qnil;
5261 XPROCESS (proc)->status = Fcons (Qexit, Fcons (make_number (256), Qnil)); 5373 p->status = Fcons (Qexit, Fcons (make_number (256), Qnil));
5262 XSETINT (XPROCESS (proc)->tick, ++process_tick); 5374 XSETINT (p->tick, ++process_tick);
5263 deactivate_process (proc); 5375 deactivate_process (proc);
5264#ifdef VMS 5376#ifdef VMS
5265 error ("Error writing to process %s; closed it", 5377 error ("Error writing to process %s; closed it", SDATA (p->name));
5266 SDATA (XPROCESS (proc)->name));
5267#else 5378#else
5268 error ("SIGPIPE raised on process %s; closed it", 5379 error ("SIGPIPE raised on process %s; closed it", SDATA (p->name));
5269 SDATA (XPROCESS (proc)->name));
5270#endif 5380#endif
5271 } 5381 }
5272 5382
@@ -6503,6 +6613,11 @@ init_process ()
6503 FD_ZERO (&non_process_wait_mask); 6613 FD_ZERO (&non_process_wait_mask);
6504 max_process_desc = 0; 6614 max_process_desc = 0;
6505 6615
6616#ifdef ADAPTIVE_READ_BUFFERING
6617 process_output_delay_count = 0;
6618 process_output_skip = 0;
6619#endif
6620
6506 FD_SET (0, &input_wait_mask); 6621 FD_SET (0, &input_wait_mask);
6507 6622
6508 Vprocess_alist = Qnil; 6623 Vprocess_alist = Qnil;
@@ -6636,6 +6751,20 @@ then a pipe is used in any case.
6636The value takes effect when `start-process' is called. */); 6751The value takes effect when `start-process' is called. */);
6637 Vprocess_connection_type = Qt; 6752 Vprocess_connection_type = Qt;
6638 6753
6754#ifdef ADAPTIVE_READ_BUFFERING
6755 DEFVAR_LISP ("process-adaptive-read-buffering", &Vprocess_adaptive_read_buffering,
6756 doc: /* If non-nil, improve receive buffering by delaying after short reads.
6757On some systems, when emacs reads the output from a subprocess, the output data
6758is read in very small blocks, potentially resulting in very poor performance.
6759This behaviour can be remedied to some extent by setting this variable to a
6760non-nil value, as it will automatically delay reading from such processes, to
6761allowing them to produce more output before emacs tries to read it.
6762If the value is t, the delay is reset after each write to the process; any other
6763non-nil value means that the delay is not reset on write.
6764The variable takes effect when `start-process' is called. */);
6765 Vprocess_adaptive_read_buffering = Qt;
6766#endif
6767
6639 defsubr (&Sprocessp); 6768 defsubr (&Sprocessp);
6640 defsubr (&Sget_process); 6769 defsubr (&Sget_process);
6641 defsubr (&Sget_buffer_process); 6770 defsubr (&Sget_buffer_process);