branch: elpa/el-job
commit e52b70fd12301fc77b8d6c350548aaf588781219
Author: Martin Edström <meedstro...@gmail.com>
Commit: Martin Edström <meedstro...@gmail.com>

    Do not spawn more processes than needed
---
 el-job.el | 75 +++++++++++++++++++++++++++++++--------------------------------
 1 file changed, 37 insertions(+), 38 deletions(-)

diff --git a/el-job.el b/el-job.el
index 592c40f4e8..fdc87d2f61 100644
--- a/el-job.el
+++ b/el-job.el
@@ -284,6 +284,7 @@ with one character of your choosing, such as a dot."
                       (:conc-name el-job:))
   id
   callback
+  (n-cores-to-use 1)
   (ready nil :documentation "Processes ready for input.")
   (busy nil :documentation "Processes that have not yet returned output.")
   stderr
@@ -339,7 +340,7 @@ Usually, it would be a function you have written yourself, 
and you pass
 LOAD-FEATURES to indicate where to find that Emacs Lisp file, plus any
 dependencies not built into Emacs.
 
-LOAD-FEATURES is a list of symbols like those in `features'; the files
+LOAD-FEATURES is a list of symbols like those in `features'\; the files
 in question should end with a `provide' call on the same symbols.
 
 The subprocesses do not inherit `load-path', it is the current Emacs
@@ -404,7 +405,7 @@ For debugging, see these commands:
                  (puthash id (el-job--make :id id) el-jobs)))
         (do-respawn nil)
         (do-exec nil))
-    (el-job--with job ( .queued-inputs .busy .ready
+    (el-job--with job ( .queued-inputs .busy .ready .n-cores-to-use
                         .spawn-args .callback .timestamps )
       (unless (and .busy (eq if-busy 'noop))
         (plist-put .timestamps :launched (current-time))
@@ -422,16 +423,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))
+          ;; Prevent spawning a dozen processes when you'll use only one or two
+          (let ((machine-cores (max 1 (1- (num-processors)))))
+            (setf .n-cores-to-use (if (length< .queued-inputs machine-cores)
+                                      (length .queued-inputs)
+                                    machine-cores))
+            (when (or (length< .ready .n-cores-to-use)
+                      (not (seq-every-p #'process-live-p .ready)))
+              (setq do-respawn t)))
           (let ((new-spawn-args (list job
                                       load-features
                                       inject-vars
@@ -451,29 +450,29 @@ For debugging, see these commands:
   "Spin up processes for JOB, standing by for input.
 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)
-           (print-circle t)
-           (print-symbols-bare t)
-           (print-escape-newlines t)
-           (print-escape-nonascii t) ;; Prolly unnecessary
-           (vars (prin1-to-string
-                  (cl-loop for var in inject-vars
-                           if (symbolp var)
-                           collect (cons var (symbol-value var))
-                           else collect var)))
-           (libs (prin1-to-string
-                  (mapcar #'el-job--ensure-compiled-lib load-features)))
-           (command
-            (list
-             (file-name-concat invocation-directory invocation-name)
-             "--quick"
-             "--batch"
-             "--load" (el-job--ensure-compiled-lib 'el-job-child)
-             "--eval" (format "(el-job-child--work #'%S)" funcall-per-input)))
-           ;; Ensure the working directory is not remote (it messes things up)
-           (default-directory invocation-directory))
+  (let* ((print-length nil)
+         (print-level nil)
+         (print-circle t)
+         (print-symbols-bare t)
+         (print-escape-newlines t)
+         (print-escape-nonascii t) ;; Prolly unnecessary
+         (vars (prin1-to-string
+                (cl-loop for var in inject-vars
+                         if (symbolp var)
+                         collect (cons var (symbol-value var))
+                         else collect var)))
+         (libs (prin1-to-string
+                (mapcar #'el-job--ensure-compiled-lib load-features)))
+         (command
+          (list
+           (file-name-concat invocation-directory invocation-name)
+           "--quick"
+           "--batch"
+           "--load" (el-job--ensure-compiled-lib 'el-job-child)
+           "--eval" (format "(el-job-child--work #'%S)" funcall-per-input)))
+         ;; Ensure the working directory is not remote (it messes things up)
+         (default-directory invocation-directory))
+    (el-job--with job (.stderr .id .ready .spawn-args .n-cores-to-use)
       (setf .stderr
             (with-current-buffer
                 (get-buffer-create (format " *el-job:%s:err*" .id) t)
@@ -481,7 +480,7 @@ see `el-job-launch'."
               (erase-buffer)
               (current-buffer)))
       (condition-case err
-          (dotimes (i (max 1 (1- (num-processors))))
+          (dotimes (i .n-cores-to-use)
             (let ((proc (make-process
                          :name (format "el-job:%s:%d" .id i)
                          :noquery t
@@ -514,14 +513,14 @@ This puts them to work.  Each successful child will print 
output
 \(even nil output) to its associated process buffer, whereupon something
 should trigger `el-job--handle-output'."
   (el-job--with job
-      ( .ready .busy .input-sets .result-sets .queued-inputs
+      ( .ready .busy .input-sets .result-sets .queued-inputs .n-cores-to-use
         .past-elapsed .timestamps .finish-times .id .stderr .poll-timer )
     (cancel-timer .poll-timer)
     (setf .input-sets nil)
     (setf .result-sets nil)
     (setf .finish-times nil)
     (let ((splits (el-job--split-optimally .queued-inputs
-                                           (max 1 (1- (num-processors)))
+                                           .n-cores-to-use
                                            .past-elapsed))
           busy-bufs)
       (unless (length< splits (1+ (length .ready)))

Reply via email to