mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-15 10:30:25 -08:00
Be more efficient when buffering output in Eshell
This makes the built-in 'eshell/cat' 5-10x faster on large files in my (somewhat limited) tests. In addition, this change periodically redisplays when using the Eshell buffered output so that users can see some progress. * lisp/eshell/esh-io.el (eshell-print-queue-size, eshell-print-queue, eshell-print-queue-count): Make obsolete in favor of... (eshell-buffered-print-size, eshell--buffered-print-queue) (eshell--buffered-print-current-size): ... these. (eshell-buffered-print-redisplay-throttle): New user option. (eshell--buffered-print-next-redisplay): New variable. (eshell-init-print-buffer): Make obsolete. (eshell-flush): Add new REDISPLAY-NOW argument in favor of CLEAR (which only 'eshell-init-print-buffer' should have used). (eshell-buffered-print): Compare queued output length to 'eshell--buffered-print-current-size'. (eshell-with-buffered-print): New macro. * lisp/eshell/esh-var.el (eshell/env): * lisp/eshell/em-dirs.el (eshell/cd): * lisp/eshell/em-hist.el (eshell/history): * lisp/eshell/em-unix.el (eshell/cat): * lisp/eshell/em-ls.el (eshell/ls): Use 'eshell-with-buffered-print'. (flush-func): Remove. (eshell-ls--insert-directory, eshell-do-ls): Remove 'flush-func'. * test/lisp/eshell/em-unix-tests.el (em-unix-test/compile/interactive) (em-unix-test/compile/pipeline, em-unix-test/compile/subcommand): Fix indentation. (em-unix-test/cat/file-output): New test. * etc/NEWS: Announce these improvements.
This commit is contained in:
parent
c69c822c59
commit
2fac71255f
8 changed files with 143 additions and 77 deletions
|
|
@ -112,10 +112,30 @@ other buffers)."
|
|||
|
||||
(defcustom eshell-print-queue-size 5
|
||||
"The size of the print queue, for doing buffered printing.
|
||||
This is basically a speed enhancement, to avoid blocking the Lisp code
|
||||
from executing while Emacs is redisplaying."
|
||||
This variable is obsolete. You should use `eshell-buffered-print-size'
|
||||
instead."
|
||||
:type 'integer
|
||||
:group 'eshell-io)
|
||||
(make-obsolete-variable 'eshell-print-queue-size
|
||||
'eshell-buffered-print-size "30.1")
|
||||
|
||||
(defcustom eshell-buffered-print-size 2048
|
||||
"The size of the print queue in characters, for doing buffered printing.
|
||||
Larger values for this option will generally result in faster execution
|
||||
by reducing the overhead associated with each print operation, but will
|
||||
increase the time it takes to see any progress in the output; smaller
|
||||
values will do the reverse."
|
||||
:type 'integer
|
||||
:group 'eshell-io
|
||||
:version "30.1")
|
||||
|
||||
(defcustom eshell-buffered-print-redisplay-throttle 0.025
|
||||
"The minimum time in seconds between redisplays when using buffered printing.
|
||||
If nil, don't redisplay while printing."
|
||||
:type '(choice number
|
||||
(const :tag "Don't redisplay" nil))
|
||||
:group 'eshell-io
|
||||
:version "30.1")
|
||||
|
||||
(defcustom eshell-virtual-targets
|
||||
'(;; The literal string "/dev/null" is intentional here. It just
|
||||
|
|
@ -460,40 +480,74 @@ INDEX is the handle index to check. If nil, check
|
|||
(equal (caar (aref handles eshell-error-handle)) '(t)))
|
||||
(equal (caar (aref handles index)) '(t)))))
|
||||
|
||||
(defvar eshell--buffered-print-queue nil)
|
||||
(defvar eshell--buffered-print-current-size nil)
|
||||
(defvar eshell--buffered-print-next-redisplay nil)
|
||||
|
||||
(defvar eshell-print-queue nil)
|
||||
(make-obsolete-variable 'eshell-print-queue
|
||||
'eshell--buffered-print-queue "30.1")
|
||||
(defvar eshell-print-queue-count -1)
|
||||
(make-obsolete-variable 'eshell-print-queue-count
|
||||
'eshell--buffered-print-current-size "30.1")
|
||||
|
||||
(defsubst eshell-print (object)
|
||||
"Output OBJECT to the standard output handle."
|
||||
(eshell-output-object object eshell-output-handle))
|
||||
|
||||
(defun eshell-flush (&optional reset-p)
|
||||
"Flush out any lines that have been queued for printing.
|
||||
Must be called before printing begins with -1 as its argument, and
|
||||
after all printing is over with no argument."
|
||||
(ignore
|
||||
(if reset-p
|
||||
(setq eshell-print-queue nil
|
||||
eshell-print-queue-count reset-p)
|
||||
(if eshell-print-queue
|
||||
(eshell-print eshell-print-queue))
|
||||
(eshell-flush 0))))
|
||||
|
||||
(defun eshell-init-print-buffer ()
|
||||
"Initialize the buffered printing queue."
|
||||
(eshell-flush -1))
|
||||
(declare (obsolete #'eshell-with-buffered-print "30.1"))
|
||||
(setq eshell--buffered-print-queue nil
|
||||
eshell--buffered-print-current-size 0))
|
||||
|
||||
(defun eshell-flush (&optional redisplay-now)
|
||||
"Flush out any text that has been queued for printing.
|
||||
When printing interactively, this will call `redisplay' every
|
||||
`eshell-buffered-print-redisplay-throttle' seconds so that the user can
|
||||
see the progress. If REDISPLAY-NOW is non-nil, call `redisplay' for
|
||||
interactive output even if the throttle would otherwise prevent it."
|
||||
(ignore
|
||||
(when eshell--buffered-print-queue
|
||||
(eshell-print (apply #'concat eshell--buffered-print-queue))
|
||||
;; When printing interactively (see `eshell-with-buffered-print'),
|
||||
;; periodically redisplay so the user can see some progress.
|
||||
(when (and eshell--buffered-print-next-redisplay
|
||||
(or redisplay-now
|
||||
(time-less-p eshell--buffered-print-next-redisplay
|
||||
(current-time))))
|
||||
(redisplay)
|
||||
(setq eshell--buffered-print-next-redisplay
|
||||
(time-add eshell--buffered-print-next-redisplay
|
||||
eshell-buffered-print-redisplay-throttle)))
|
||||
(setq eshell--buffered-print-queue nil
|
||||
eshell--buffered-print-current-size 0))))
|
||||
|
||||
(defun eshell-buffered-print (&rest strings)
|
||||
"A buffered print -- *for strings only*."
|
||||
(if (< eshell-print-queue-count 0)
|
||||
(progn
|
||||
(eshell-print (apply 'concat strings))
|
||||
(setq eshell-print-queue-count 0))
|
||||
(if (= eshell-print-queue-count eshell-print-queue-size)
|
||||
(eshell-flush))
|
||||
(setq eshell-print-queue
|
||||
(concat eshell-print-queue (apply 'concat strings))
|
||||
eshell-print-queue-count (1+ eshell-print-queue-count))))
|
||||
"A buffered print -- *for strings only*.
|
||||
When the buffer exceeds `eshell-buffered-print-size' in characters, this
|
||||
will flush it using `eshell-flush' (which see)."
|
||||
(setq eshell--buffered-print-queue
|
||||
(nconc eshell--buffered-print-queue strings))
|
||||
(cl-incf eshell--buffered-print-current-size
|
||||
(apply #'+ (mapcar #'length strings)))
|
||||
(when (> eshell--buffered-print-current-size eshell-buffered-print-size)
|
||||
(eshell-flush)))
|
||||
|
||||
(defmacro eshell-with-buffered-print (&rest body)
|
||||
"Initialize buffered printing for Eshell, and then evaluate BODY.
|
||||
Within BODY, call `eshell-buffered-print' to perform output."
|
||||
(declare (indent 0))
|
||||
`(let ((eshell--buffered-print-queue nil)
|
||||
(eshell--buffered-print-current-size 0)
|
||||
(eshell--buffered-print-next-redisplay
|
||||
(when (and eshell-buffered-print-redisplay-throttle
|
||||
(eshell-interactive-output-p))
|
||||
(time-add (current-time)
|
||||
eshell-buffered-print-redisplay-throttle))))
|
||||
(unwind-protect
|
||||
,@body
|
||||
(eshell-flush))))
|
||||
|
||||
(defsubst eshell-error (object)
|
||||
"Output OBJECT to the standard error handle."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue