branch: externals/el-job commit 183ff2e77549ce32a4d4e1cd4037c37b119b61c9 Author: Martin Edström <meedstro...@gmail.com> Commit: Martin Edström <meedstro...@gmail.com>
Polish --- README.org | 17 +++++++++++++---- el-job.el | 31 ++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/README.org b/README.org index 2fe63f2849..40857d2013 100644 --- a/README.org +++ b/README.org @@ -36,18 +36,27 @@ Users who tend to run system commands such as =pkill emacs= may find that the co *** Emacs 30 =fast-read-process-output= Some other libraries, like the popular [[https://github.com/jwiegley/emacs-async/][async.el]], are designed around a custom process filter. -Since Emacs 30, it's a good idea to instead use the /built-in/ process filter when performance is critical, and el-job does so. +Since Emacs 30, it's a good idea to instead use the /built-in/ process filter when performance is critical, and el-job does so. Quoting [[https://github.com/emacs-mirror/emacs/blob/master/etc/NEWS.30][NEWS.30]]: -A corollary: if you're testing this on Emacs 29 or below, you don't see this library at its best performance. +#+begin_src org +,** The default process filter was rewritten in native code. +The round-trip through the Lisp function +'internal-default-process-filter' is skipped when the process filter is +the default one. It is reimplemented in native code, reducing GC churn. +To undo this change, set 'fast-read-process-output' to nil. +#+end_src ** News 2.1.0 - DROP SUPPORT Emacs 28 - - It likely has not been working for a while anyway. May work if you downgrade to [[https://github.com/meedstrom/el-job/tree/v0.3][v0.3 branch]]. + - It likely has not been working for a while anyway. Maybe works on the [[https://github.com/meedstrom/el-job/tree/v0.3][v0.3 branch]], from 0.3.26+. ** News 2.0.0 -- Jobs must now have :id (no more anonymous jobs) +- Jobs must now have =:id= (no more anonymous jobs). - Pruned many code paths. +** News 1.1.0 +- Changed internals so that all builds of Emacs can be expected to perform similarly well. + ** News 1.0.0 - No longer keeps processes alive forever. All jobs are kept alive for up to 30 seconds of disuse, then reaped. - Pruned many code paths. diff --git a/el-job.el b/el-job.el index 90f076e828..592c40f4e8 100644 --- a/el-job.el +++ b/el-job.el @@ -409,7 +409,7 @@ For debugging, see these commands: (unless (and .busy (eq if-busy 'noop)) (plist-put .timestamps :launched (current-time)) ;; TODO: Can we somehow defer this to even later? - ;; Maybe if-busy=wait means don't funcall? + ;; Maybe if-busy=wait could inhibit funcalling it? (when (functionp inputs) (setq inputs (funcall inputs))) (if .busy @@ -422,6 +422,14 @@ For debugging, see these commands: (setq do-exec t)) (when do-exec (setf .callback callback) + ;; TODO: Complicate the code-base with this? + ;; (let ((machine-cores (max 1 (1- (num-processors))))) + ;; (setf .n-cores-to-use (if (length< inputs machine-cores) + ;; (length inputs) + ;; machine-cores))) + ;; (when (or (length< .ready .n-cores-to-use) + ;; (not (seq-every-p #'process-live-p .ready))) + ;; (setq do-respawn t)) (unless (and .ready (seq-every-p #'process-live-p .ready)) (setq do-respawn t)) (let ((new-spawn-args (list job @@ -441,7 +449,8 @@ For debugging, see these commands: (defvar-local el-job-here nil) (defun el-job--spawn-processes (job load-features inject-vars funcall-per-input) "Spin up processes for JOB, standing by for input. -For the rest of the arguments, see `el-job-launch'." +For arguments LOAD-FEATURES INJECT-VARS FUNCALL-PER-INPUT, +see `el-job-launch'." (el-job--with job (.stderr .id .ready .spawn-args) (let* ((print-length nil) (print-level nil) @@ -557,8 +566,11 @@ should trigger `el-job--handle-output'." ;; but spread out the last 7 polls between T-minus-20s and T-minus-30s. (defun el-job--poll (n bufs) + "Check process buffers BUFS for complete output. +For each where it is complete, handle it. For the rest, check again +after a short delay. N is the count of checks done so far." (cl-assert (not (null bufs))) - (let (busy-bufs id) + (let (busy-bufs) (save-current-buffer (dolist (buf bufs) (if (not (buffer-live-p buf)) @@ -567,12 +579,12 @@ should trigger `el-job--handle-output'." (if (eq (char-before) ?\n) (el-job--handle-output) (push buf busy-bufs)))) - (when bufs - (if (and busy-bufs (<= n 42)) - (setf (el-job:poll-timer el-job-here) - (run-with-timer - (/ n (float (ash 1 5))) nil #'el-job--poll (1+ n) busy-bufs)) - (setq id (el-job:id el-job-here)) + (cl-assert el-job-here) + (if (and busy-bufs (<= n 42)) + (setf (el-job:poll-timer el-job-here) + (run-with-timer + (/ n (float (ash 1 5))) nil #'el-job--poll (1+ n) busy-bufs)) + (let ((id (el-job:id el-job-here))) (el-job--disable el-job-here) (if busy-bufs (message "el-job: Timed out, was busy for 30+ seconds: %s" id) @@ -653,6 +665,7 @@ same ID still has the benchmarks table and possibly queued input." ;;; Tools / public API (defun el-job-cycle-debug-level () + "Increment `el-job--debug-level'." (interactive) (message "Variable `el-job--debug-level' set to %d" (setq el-job--debug-level (% (1+ el-job--debug-level) 3))))