emacs-devel
[Top][All Lists]
Advanced

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

Re: Why does adding a useless copy-sequence and discarding the result ma


From: Clément Pit-Claudel
Subject: Re: Why does adding a useless copy-sequence and discarding the result make my ELisp 40 times faster?
Date: Sat, 25 Mar 2017 09:45:26 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0

On 2017-03-25 03:05, Eli Zaretskii wrote:
>> From: Clément Pit-Claudel <address@hidden> Date: Sat, 25 Mar
>> 2017 00:24:20 -0400
>> 
>> On 2017-03-25 00:06, Clément Pit-Claudel wrote:
>>> * Why does running additional, supposedly useless code speed
>>> things up so much? (1)
>> 
>> Interestingly, it turns out that (copy-sequence) isn't needed:
>> instead, it's enough to use (sleep-for 0.000001) (or even
>> (sleep-for cl-least-positive-normalized-float)) to get the 40x
>> speedup.
> 
> Because, if you don't sleep, the process is not yet running by the 
> time you get to process-send-string, and then Emacs waits for a much 
> longer time for it to become running?

Quick experiments suggest this isn't the case: hoisting the (sleep) calls out 
of the loop and sleeping n-inner-loops times instead yields much slower code 
than when the sleep calls are interleaved with the process-send-string calls.
That is, I don't observe the aforementioned speedup if I sleep a single, "long" 
time before the loop, instead of putting a small sleep in each iteration.

Similarly, taking the process creation out of the function being timed, then 
adding a long sleep and a call to accept-process-output before the benchmarked 
code doesn't change performance significantly:

(benchmark-send-string t 200 65536 proc) → (0.013895306 0 0.0)
(benchmark-send-string nil 200 65536 proc) → (2.3035461760000002 0 0.0)

I used this code to test this:

(require 'cl-lib)
(cl-float-limits)

(defun benchmark-send-string (cargo-cult n-inner-loops size proc)
  (let* ((message (make-string size ?a)))
    (dotimes (_ n-inner-loops)
      (when cargo-cult
        (sleep-for cl-least-positive-normalized-float))
      (process-send-string proc message))
    (kill-process proc)))

(pcase-let ((`(,cargo-cult ,n-inner-loops ,size . ,prog) argv))
  (setq cargo-cult (read cargo-cult))
  (setq size (string-to-number size))
  (setq n-inner-loops (string-to-number n-inner-loops))
  (let* ((process-connection-type nil)
         (proc (apply #'start-process "reader" nil prog))
         (form `(benchmark-send-string ,cargo-cult ,n-inner-loops ,size proc)))
    (sleep-for 1.0)
    (accept-process-output nil 1.0)
    (message "%S → %S" form (eval `(benchmark-run 1 ,form)))))

(setq argv nil)

Clément.






reply via email to

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