[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

tramp (2.1.6); Unnecessary delays accept-process-output; proposed fix

From: Wagemans, Peter
Subject: tramp (2.1.6); Unnecessary delays accept-process-output; proposed fix
Date: Wed, 30 Aug 2006 11:41:01 +0200

On 2006.02.20 I sent a mail to the list with the title

    tramp (2.0.47); Unnecessary delays accept-process-output; proposed fix.

It involved the accept-process-output timeout which was set to 1
second in the tramp code. This means that emacs always waits a full
second for output from a subprocess. In my environment, this increased
total setup time for new connections by about nine seconds. The
proposed fix reduced the timeout to 0.1 second on architectures that
support it.  [In my situation, much shorter timeouts were not
productive since they typically led to emacs doing more wait requests
until subprocess output was complete.]

Michael Albinus declined the patch for the 2.0 release for stability
reasons but encouraged investigation for 2.1.

Since I'm now looking at getting 2.1.6 working, below is a similar
patch for that tramp release. I can imagine other ways of doing it,
but this seemed a relatively simple approach.

Tramp 2.1 is better in total connection setup time and the improvement
is therefore less than for tramp 2.0 (I haven't made precise
measurements), but still I see no point in having unnecessarily long
wait times.


Peter Wagemans

--- tramp.el.old_200608180843   2006-08-08 12:00:40.000000000 +0200
+++ tramp.el    2006-08-18 09:47:39.595817600 +0200
@@ -1299,6 +1299,40 @@
   :group 'tramp
   :type '(choice (const nil) (const t) (const pty)))
+(defcustom tramp-accept-process-output-timeout
+;; Try to figure out whether the system supports waiting for
+;; fractional seconds by sleeping for a millisecond. This should
+;; generate an error if the support is lacking, according to the elisp
+;; 21.2-8 manual and the following code in dispnew.c (21.4a).
+;; #ifndef EMACS_HAS_USECS
+;;   if (sec == 0 && usec != 0)
+;;     error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
+;; #endif
+(condition-case nil
+    (progn (sleep-for 0 1) 0.1)
+  (error 1) )
+;; Documentation string:
+  "Time interval to listen for output from subprocesses.
+The default value is 0.1 second on systems that support waiting
+for fractional seconds. On systems without such support,
+fractional values are rounded down, thus values smaller than 1
+second result in a zero wait time. This could result in a busy
+loop with tramp wasting CPU cycles on matching regular
+expressions against incomplete subprocess output. Therefore the
+default value is 1 second on systems without wait support for
+fractional seconds."
+  :group 'tramp
+  :type 'number)
 ;;; Internal Variables:
 (defvar tramp-md5-function
@@ -4943,7 +4977,7 @@
       (while (not found)
        ;; Reread output once all actions have been performed.
        ;; Obviously, the output was not complete.
-       (tramp-accept-process-output proc 1)
+       (tramp-accept-process-output proc tramp-accept-process-output-timeout)
        (setq todo actions)
        (while todo
          (setq item (pop todo))
@@ -4973,14 +5007,40 @@
 ;; Utility functions.
-(defun tramp-accept-process-output (&optional proc timeout timeout-msecs)
+(defun tramp-accept-process-output (&optional proc timeout)
   "Like `accept-process-output' for Tramp processes.
 This is needed in order to hide `last-coding-system-used', which is set
-for process communication also."
+for process communication also. In contrast to accept-process-output,
+the timeout is a single floating point value, usually set from the
+tramp-accept-process-output-timeout variable."
   (with-current-buffer (process-buffer proc)
     (tramp-message proc 10 "%s %s" proc (process-status proc))
     (let (buffer-read-only last-coding-system-used)
-      (accept-process-output proc timeout timeout-msecs))
+      (if timeout
+         ;; Call accept-process-output with appropriate parameters
+         ;; based on timeout value. The elisp manual 2.8 for emacs
+         ;; 21.2 (latest on 20060217) says about
+         ;; accept-process-output: "The argument seconds need not be
+         ;; an integer. If it is a floating point number, this
+         ;; function waits for a fractional number of seconds."
+         ;; However, the implementation in emacs-21.4a (current on
+         ;; 20060217) accepts only integers:
+         ;;
+         ;;   if (! NILP (timeout))
+         ;;     {
+         ;;       CHECK_NUMBER (timeout, 1);
+         ;;       seconds = XINT (timeout);
+         ;;
+         ;; so we convert the wait time to seconds and microseconds.
+         (let ((secs (floor timeout))
+               (microsecs (floor (* (mod timeout 1) 1000000))))
+           (accept-process-output proc secs microsecs))
+       ;; else call without timeout parameters
+       (accept-process-output proc)))
     (tramp-message proc 10 "\n%s" (buffer-string))))
 (defun tramp-check-for-regexp (proc regexp)
@@ -5020,13 +5080,13 @@
               (with-timeout (timeout)
                 (while (not found)
-                  (tramp-accept-process-output proc 1)
+                  (tramp-accept-process-output proc tramp-accept-process-output-timeout)
                   (unless (memq (process-status proc) '(run open))
                     (tramp-error proc 'file-error "Process has died"))
                   (setq found (tramp-check-for-regexp proc regexp))))))
             (while (not found)
-              (tramp-accept-process-output proc 1)
+              (tramp-accept-process-output proc tramp-accept-process-output-timeout)
               (unless (memq (process-status proc) '(run open))
                 (tramp-error proc 'file-error "Process has died"))
               (setq found (tramp-check-for-regexp proc regexp)))))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]