aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorDmitry Gutov2023-09-24 01:19:14 +0300
committerDmitry Gutov2024-06-09 02:44:19 +0300
commitbbc18031aff6f22a1f2b63355f18f294fbdeb797 (patch)
tree821536d84a47d3abc01490038e970c1bc53f8447 /src/process.c
parente2527dd9fd376b15d2f59ae440858b442b069577 (diff)
downloademacs-bbc18031aff6f22a1f2b63355f18f294fbdeb797.tar.gz
emacs-bbc18031aff6f22a1f2b63355f18f294fbdeb797.zip
Go around calling the default process filter (reducing GC churn)
Instead of allocating strings and passing them to the filter, pass the char buffer to a C function implementing the same logic. * src/process.c (read_process_output_before_insert) (read_process_output_after_insert): New functions, extracted from internal-default-process-filter. (Finternal_default_process_filter): Use them. (read_and_insert_process_output): New function. Use them. (read_process_output_fast): New variable. (read_process_output): Use it to choose how to insert (bug#66020). * etc/NEWS: Mention the change.
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c198
1 files changed, 143 insertions, 55 deletions
diff --git a/src/process.c b/src/process.c
index d716453631e..2e8dd758b3c 100644
--- a/src/process.c
+++ b/src/process.c
@@ -6146,6 +6146,11 @@ read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars,
6146 ssize_t nbytes, 6146 ssize_t nbytes,
6147 struct coding_system *coding); 6147 struct coding_system *coding);
6148 6148
6149static void
6150read_and_insert_process_output (struct Lisp_Process *p, char *buf,
6151 ssize_t nread,
6152 struct coding_system *process_coding);
6153
6149/* Read pending output from the process channel, 6154/* Read pending output from the process channel,
6150 starting with our buffered-ahead character if we have one. 6155 starting with our buffered-ahead character if we have one.
6151 Yield number of decoded characters read, 6156 Yield number of decoded characters read,
@@ -6261,7 +6266,10 @@ read_process_output (Lisp_Object proc, int channel)
6261 friends don't expect current-buffer to be changed from under them. */ 6266 friends don't expect current-buffer to be changed from under them. */
6262 record_unwind_current_buffer (); 6267 record_unwind_current_buffer ();
6263 6268
6264 read_and_dispose_of_process_output (p, chars, nbytes, coding); 6269 if (read_process_output_fast && p->filter == Qinternal_default_process_filter)
6270 read_and_insert_process_output (p, chars, nbytes, coding);
6271 else
6272 read_and_dispose_of_process_output (p, chars, nbytes, coding);
6265 6273
6266 /* Handling the process output should not deactivate the mark. */ 6274 /* Handling the process output should not deactivate the mark. */
6267 Vdeactivate_mark = odeactivate; 6275 Vdeactivate_mark = odeactivate;
@@ -6271,6 +6279,128 @@ read_process_output (Lisp_Object proc, int channel)
6271} 6279}
6272 6280
6273static void 6281static void
6282read_process_output_before_insert (struct Lisp_Process *p, Lisp_Object *old_read_only,
6283 ptrdiff_t *old_begv, ptrdiff_t *old_zv,
6284 ptrdiff_t *before, ptrdiff_t *before_byte,
6285 ptrdiff_t *opoint, ptrdiff_t *opoint_byte)
6286{
6287 Fset_buffer (p->buffer);
6288 *opoint = PT;
6289 *opoint_byte = PT_BYTE;
6290 *old_read_only = BVAR (current_buffer, read_only);
6291 *old_begv = BEGV;
6292 *old_zv = ZV;
6293
6294 bset_read_only (current_buffer, Qnil);
6295
6296 /* Insert new output into buffer at the current end-of-output
6297 marker, thus preserving logical ordering of input and output. */
6298 if (XMARKER (p->mark)->buffer)
6299 set_point_from_marker (p->mark);
6300 else
6301 SET_PT_BOTH (ZV, ZV_BYTE);
6302 *before = PT;
6303 *before_byte = PT_BYTE;
6304
6305 /* If the output marker is outside of the visible region, save
6306 the restriction and widen. */
6307 if (! (BEGV <= PT && PT <= ZV))
6308 Fwiden ();
6309}
6310
6311static void
6312read_process_output_after_insert (struct Lisp_Process *p, Lisp_Object *old_read_only,
6313 ptrdiff_t old_begv, ptrdiff_t old_zv,
6314 ptrdiff_t before, ptrdiff_t before_byte,
6315 ptrdiff_t opoint, ptrdiff_t opoint_byte)
6316{
6317 struct buffer *b;
6318
6319 /* Make sure the process marker's position is valid when the
6320 process buffer is changed in the signal_after_change above.
6321 W3 is known to do that. */
6322 if (BUFFERP (p->buffer)
6323 && (b = XBUFFER (p->buffer), b != current_buffer))
6324 set_marker_both (p->mark, p->buffer, BUF_PT (b), BUF_PT_BYTE (b));
6325 else
6326 set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
6327
6328 update_mode_lines = 23;
6329
6330 /* Make sure opoint and the old restrictions
6331 float ahead of any new text just as point would. */
6332 if (opoint >= before)
6333 {
6334 opoint += PT - before;
6335 opoint_byte += PT_BYTE - before_byte;
6336 }
6337 if (old_begv > before)
6338 old_begv += PT - before;
6339 if (old_zv >= before)
6340 old_zv += PT - before;
6341
6342 /* If the restriction isn't what it should be, set it. */
6343 if (old_begv != BEGV || old_zv != ZV)
6344 Fnarrow_to_region (make_fixnum (old_begv), make_fixnum (old_zv));
6345
6346 bset_read_only (current_buffer, *old_read_only);
6347 SET_PT_BOTH (opoint, opoint_byte);
6348}
6349
6350static void read_and_insert_process_output (struct Lisp_Process *p, char *buf,
6351 ssize_t nread,
6352 struct coding_system *process_coding)
6353{
6354 if (!nread || NILP (p->buffer) || !BUFFER_LIVE_P (XBUFFER (p->buffer)))
6355 return;
6356
6357 Lisp_Object old_read_only;
6358 ptrdiff_t old_begv, old_zv;
6359 ptrdiff_t before, before_byte;
6360 ptrdiff_t opoint, opoint_byte;
6361
6362 read_process_output_before_insert (p, &old_read_only, &old_begv, &old_zv,
6363 &before, &before_byte, &opoint, &opoint_byte);
6364
6365 /* Adapted from call_process. */
6366 if (NILP (BVAR (XBUFFER(p->buffer), enable_multibyte_characters))
6367 && ! CODING_MAY_REQUIRE_DECODING (process_coding))
6368 {
6369 insert_1_both (buf, nread, nread, 0, 0, 0);
6370 signal_after_change (PT - nread, 0, nread);
6371 }
6372 else
6373 { /* We have to decode the input. */
6374 Lisp_Object curbuf;
6375 int carryover = 0;
6376 specpdl_ref count1 = SPECPDL_INDEX ();
6377
6378 XSETBUFFER (curbuf, current_buffer);
6379 /* We cannot allow after-change-functions be run
6380 during decoding, because that might modify the
6381 buffer, while we rely on process_coding.produced to
6382 faithfully reflect inserted text until we
6383 TEMP_SET_PT_BOTH below. */
6384 specbind (Qinhibit_modification_hooks, Qt);
6385 decode_coding_c_string (process_coding,
6386 (unsigned char *) buf, nread, curbuf);
6387 unbind_to (count1, Qnil);
6388
6389 TEMP_SET_PT_BOTH (PT + process_coding->produced_char,
6390 PT_BYTE + process_coding->produced);
6391 signal_after_change (PT - process_coding->produced_char,
6392 0, process_coding->produced_char);
6393 carryover = process_coding->carryover_bytes;
6394 if (carryover > 0)
6395 memcpy (buf, process_coding->carryover,
6396 process_coding->carryover_bytes);
6397 }
6398
6399 read_process_output_after_insert (p, &old_read_only, old_begv, old_zv,
6400 before, before_byte, opoint, opoint_byte);
6401}
6402
6403static void
6274read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars, 6404read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars,
6275 ssize_t nbytes, 6405 ssize_t nbytes,
6276 struct coding_system *coding) 6406 struct coding_system *coding)
@@ -6373,7 +6503,6 @@ Otherwise it discards the output. */)
6373 (Lisp_Object proc, Lisp_Object text) 6503 (Lisp_Object proc, Lisp_Object text)
6374{ 6504{
6375 struct Lisp_Process *p; 6505 struct Lisp_Process *p;
6376 ptrdiff_t opoint;
6377 6506
6378 CHECK_PROCESS (proc); 6507 CHECK_PROCESS (proc);
6379 p = XPROCESS (proc); 6508 p = XPROCESS (proc);
@@ -6384,31 +6513,10 @@ Otherwise it discards the output. */)
6384 Lisp_Object old_read_only; 6513 Lisp_Object old_read_only;
6385 ptrdiff_t old_begv, old_zv; 6514 ptrdiff_t old_begv, old_zv;
6386 ptrdiff_t before, before_byte; 6515 ptrdiff_t before, before_byte;
6387 ptrdiff_t opoint_byte; 6516 ptrdiff_t opoint, opoint_byte;
6388 struct buffer *b;
6389
6390 Fset_buffer (p->buffer);
6391 opoint = PT;
6392 opoint_byte = PT_BYTE;
6393 old_read_only = BVAR (current_buffer, read_only);
6394 old_begv = BEGV;
6395 old_zv = ZV;
6396
6397 bset_read_only (current_buffer, Qnil);
6398
6399 /* Insert new output into buffer at the current end-of-output
6400 marker, thus preserving logical ordering of input and output. */
6401 if (XMARKER (p->mark)->buffer)
6402 set_point_from_marker (p->mark);
6403 else
6404 SET_PT_BOTH (ZV, ZV_BYTE);
6405 before = PT;
6406 before_byte = PT_BYTE;
6407 6517
6408 /* If the output marker is outside of the visible region, save 6518 read_process_output_before_insert (p, &old_read_only, &old_begv, &old_zv,
6409 the restriction and widen. */ 6519 &before, &before_byte, &opoint, &opoint_byte);
6410 if (! (BEGV <= PT && PT <= ZV))
6411 Fwiden ();
6412 6520
6413 /* Adjust the multibyteness of TEXT to that of the buffer. */ 6521 /* Adjust the multibyteness of TEXT to that of the buffer. */
6414 if (NILP (BVAR (current_buffer, enable_multibyte_characters)) 6522 if (NILP (BVAR (current_buffer, enable_multibyte_characters))
@@ -6421,35 +6529,8 @@ Otherwise it discards the output. */)
6421 insert_from_string_before_markers (text, 0, 0, 6529 insert_from_string_before_markers (text, 0, 0,
6422 SCHARS (text), SBYTES (text), 0); 6530 SCHARS (text), SBYTES (text), 0);
6423 6531
6424 /* Make sure the process marker's position is valid when the 6532 read_process_output_after_insert (p, &old_read_only, old_begv, old_zv,
6425 process buffer is changed in the signal_after_change above. 6533 before, before_byte, opoint, opoint_byte);
6426 W3 is known to do that. */
6427 if (BUFFERP (p->buffer)
6428 && (b = XBUFFER (p->buffer), b != current_buffer))
6429 set_marker_both (p->mark, p->buffer, BUF_PT (b), BUF_PT_BYTE (b));
6430 else
6431 set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
6432
6433 update_mode_lines = 23;
6434
6435 /* Make sure opoint and the old restrictions
6436 float ahead of any new text just as point would. */
6437 if (opoint >= before)
6438 {
6439 opoint += PT - before;
6440 opoint_byte += PT_BYTE - before_byte;
6441 }
6442 if (old_begv > before)
6443 old_begv += PT - before;
6444 if (old_zv >= before)
6445 old_zv += PT - before;
6446
6447 /* If the restriction isn't what it should be, set it. */
6448 if (old_begv != BEGV || old_zv != ZV)
6449 Fnarrow_to_region (make_fixnum (old_begv), make_fixnum (old_zv));
6450
6451 bset_read_only (current_buffer, old_read_only);
6452 SET_PT_BOTH (opoint, opoint_byte);
6453 } 6534 }
6454 return Qnil; 6535 return Qnil;
6455} 6536}
@@ -8799,6 +8880,13 @@ On GNU/Linux systems, the value should not exceed
8799/proc/sys/fs/pipe-max-size. See pipe(7) manpage for details. */); 8880/proc/sys/fs/pipe-max-size. See pipe(7) manpage for details. */);
8800 read_process_output_max = 4096; 8881 read_process_output_max = 4096;
8801 8882
8883 DEFVAR_BOOL ("read-process-output-fast", read_process_output_fast,
8884 doc: /* Non-nil to optimize the insertion of process output.
8885We skip calling `internal-default-process-filter' and don't allocate
8886the Lisp string that would be used as its argument. Only affects the
8887case of asynchronous process with the default filter. */);
8888 read_process_output_fast = Qt;
8889
8802 DEFVAR_INT ("process-error-pause-time", process_error_pause_time, 8890 DEFVAR_INT ("process-error-pause-time", process_error_pause_time,
8803 doc: /* The number of seconds to pause after handling process errors. 8891 doc: /* The number of seconds to pause after handling process errors.
8804This isn't used for all process-related errors, but is used when a 8892This isn't used for all process-related errors, but is used when a