emacs-devel
[Top][All Lists]
Advanced

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

Re: Questions about throw-on-input


From: Alexander Miller
Subject: Re: Questions about throw-on-input
Date: Sun, 10 May 2020 15:47:18 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0

I have built a simple benchmark now, and it looks like neither version
is any good.

Checking (input-pending-p) does not work in this scenario. When your
worker thread is actually busy (simulated by the 10000 calls to random
below) input-pending-p will not return t, no matter how much you hammer
the keyboard in the meatime. The yield-time message will not appear even
once. So it looks like keeping the CPU busy also prevents the processing
of input events.

The always yielding approach does not work either. All it does is give
you some extremely small windows, measured in ms at best, to make your
input, but most of the time it will be ignored anyway because of the
problem described above.

The only way I was able to get this to run smoothly was to replace the
yield with an uncoditional (sleep-for 0.00001). That allowed my input to
be processed without perceptible delay and even the performance impact
seemed to be acceptable: when compiled it increased the benchmark's
runtime from ~5 seconds to ~5.3 seconds.

So whatever you are up to, it looks like power-napping is the way to go.

Here is the benchmark code used. It'll fake recalculating all visible
files' git status in treemacs (I've started using a real git call, but
awaiting the process' output would yield the thread automatically,
throwing off my tests):

(defun extra-slow-git-reapply ()
  (let ((run-start (float-time)))
    (with-current-buffer (treemacs-get-local-buffer)
      (dotimes (_ 30)
        (goto-char (point-min))
        (forward-line 1)
        (while (= 0 (forward-line 1))
          (-when-let* ((btn (treemacs-current-button))
                       (__no-projects (null (treemacs-button-get btn :project))))
            (let* ((inhibit-read-only t)
                   (status (prog1 (random 4) (dotimes (_ 10000) (random))))
                   (face (pcase status
                           (0 'font-lock-string-face)
                           (1 'font-lock-keyword-face)
                           (2 'font-lock-variable-name-face)
                           (3 'font-lock-builtin-face))))
              (put-text-property
               (treemacs-button-start btn)
               (treemacs-button-end btn)
               'face face))
            (let ((time (float-time)))
              (when t ;;(input-pending-p)
                (thread-yield)
                (message "Yield Time %ss" (- (float-time) time))))))))
    (message "Run Time %ss" (- (float-time) run-start))))

yyoncho writes:

> Thank you, Alexander.
>
> I was planning to span a new thread but the approach with the queue might > be a better fit for us. Do you have the numbers for what will yield better
> performance - checking input-pending and then thread-yield or directly
> calling thread-yield?
>
> Ivan


reply via email to

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