unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Questions about throw-on-input
@ 2020-05-07  7:31 Ivan Yonchovski
  2020-05-07 12:36 ` Eli Zaretskii
  2020-05-07 13:49 ` Stefan Monnier
  0 siblings, 2 replies; 52+ messages in thread
From: Ivan Yonchovski @ 2020-05-07  7:31 UTC (permalink / raw)
  To: emacs-devel


Hi all,

I have few questions regarding throw-on-input:

1. In the following example:

(dotimes (_ 10)
  (message "Length %s"
           (length
            (let (result)
              (catch t
                (let ((throw-on-input t))
                  (dotimes (counter 10000000)
                    (push (number-to-string counter) result))))
              result))))

.. after I execute the following block each of the 10 computations will be
canceled after pressing C-n for example, how do I force the handling of
the command to be processed? I tried redisplay but it does not help.

2. Consider the following pieces of code:

(message "Length %s"
         (length
          (let (result)
            (catch t
              (let ((throw-on-input t))
                (dotimes (counter 10000000)
                  (push (number-to-string counter) result))))
            result)))


(run-with-idle-timer
 0.0
 nil
 (lambda ()
   (message "Length %s"
            (length
             (let (result)
               (catch t
                 (let ((throw-on-input t))
                   (dotimes (counter 10000000)
                     (push (number-to-string counter) result))))
               result)))))

The issue is with the second block, it seems like throw-on-input is
disregarded when used in run-with-idle-timer. Can anyone confirm if this
is a bug/desired behavior or I should use something else if I want to
run cancelable tasks in on-idle?

Thanks,
Ivan



^ permalink raw reply	[flat|nested] 52+ messages in thread
* Re: Questions about throw-on-input
@ 2020-05-09 13:09 Alexander Miller
  2020-05-10 11:11 ` yyoncho
  0 siblings, 1 reply; 52+ messages in thread
From: Alexander Miller @ 2020-05-09 13:09 UTC (permalink / raw)
  To: yyoncho; +Cc: emacs-devel

[I had to copy the In-Reply-To header from the page source because the
reply-to button
wouldn't set it, so let's hope I'm doing this right.]

Incidentally I have recently been playing around with a similar idea -
to use a worker thread
to split and run long tasks in the background. Here's what I came up
with so far:

(defconst worker-mutex (make-mutex "*WORKER MUTEX*"))
(defconst worker-cond-var (make-condition-variable worker-mutex))
(defvar worker-queue (list))

(setf
  worker
  (make-thread
   (lambda ()
     (while t
       (while worker-queue
         (let* ((work-unit (pop worker-queue))
                (fn (car work-unit))
                (args (cdr work-unit)))
           (apply fn args)
           (thread-yield)))
       (with-mutex worker-mutex
         (condition-wait worker-cond-var))))
   "*WORKER*"))

(setf worker-timer
       (run-with-idle-timer
        1 t (lambda ()
              (when worker-queue
                (with-mutex worker-mutex
                  (condition-notify worker-cond-var))))))

(push (list #'shell-command-to-string "notify-send 'Hello' 'World!'")
worker-queue)
(push (list #'message "Hello %s!" "World") worker-queue)
(push (list #'call-interactively #'treemacs) worker-queue)

Get enough thread-yield or input-pending checks into the work the thread
is doing and
you might just be able to get around blocking the UI despite having
plenty to do.






^ permalink raw reply	[flat|nested] 52+ messages in thread
* Re: Questions about throw-on-input
@ 2020-05-10 13:47 Alexander Miller
  2020-05-11 14:13 ` Eli Zaretskii
  0 siblings, 1 reply; 52+ messages in thread
From: Alexander Miller @ 2020-05-10 13:47 UTC (permalink / raw)
  To: yyoncho; +Cc: emacs-devel

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


^ permalink raw reply	[flat|nested] 52+ messages in thread

end of thread, other threads:[~2020-05-16 11:29 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-05-07  7:31 Questions about throw-on-input Ivan Yonchovski
2020-05-07 12:36 ` Eli Zaretskii
2020-05-07 14:28   ` Ivan Yonchovski
2020-05-07 21:11   ` yyoncho
2020-05-08  1:58     ` Stefan Monnier
2020-05-08  4:36       ` yyoncho
2020-05-08  4:43         ` yyoncho
2020-05-12  4:15       ` Michael Heerdegen
2020-05-08 10:41     ` Eli Zaretskii
2020-05-08 11:23       ` Ivan Yonchovski
2020-05-08 11:45         ` Eli Zaretskii
2020-05-08 11:55           ` yyoncho
2020-05-08 14:55         ` Stefan Monnier
2020-05-08 18:04           ` yyoncho
2020-05-07 13:49 ` Stefan Monnier
2020-05-07 15:36   ` Ivan Yonchovski
  -- strict thread matches above, loose matches on Subject: below --
2020-05-09 13:09 Alexander Miller
2020-05-10 11:11 ` yyoncho
2020-05-10 13:47 Alexander Miller
2020-05-11 14:13 ` Eli Zaretskii
2020-05-11 15:21   ` Stefan Monnier
2020-05-11 16:19     ` Eli Zaretskii
2020-05-11 17:27       ` Stefan Monnier
2020-05-11 17:39         ` Alexander Miller
2020-05-11 18:23           ` Eli Zaretskii
2020-05-11 18:24           ` Stefan Monnier
2020-05-11 19:48             ` Alexander Miller
2020-05-11 20:14               ` Stefan Monnier
2020-05-12 22:33                 ` Alexander Miller
2020-05-13 14:43                   ` Eli Zaretskii
2020-05-13 18:47                     ` Alexander Miller
2020-05-14  8:32                     ` Philipp Stephani
2020-05-14 14:23                       ` Eli Zaretskii
2020-05-14 14:37                         ` Philipp Stephani
2020-05-14 16:56                       ` Drew Adams
2020-05-15  3:21                         ` Richard Stallman
2020-05-15  3:54                           ` Stefan Monnier
2020-05-15  8:19                             ` Arthur Miller
2020-05-15 15:45                               ` Stefan Monnier
2020-05-15 16:46                                 ` Yuan Fu
2020-05-15 17:31                                   ` Stefan Monnier
2020-05-15 17:50                                     ` yyoncho
2020-05-15 18:44                                       ` Alexander Miller
2020-05-15 18:55                                         ` Stefan Monnier
2020-05-15 19:46                                         ` Philipp Stephani
2020-05-15 18:00                                     ` Andrea Corallo
2020-05-15 17:35                                 ` Arthur Miller
2020-05-15 19:47                                 ` chad
2020-05-16 11:29                                   ` Eli Zaretskii
2020-05-12  2:39           ` Daniel Colascione
2020-05-12 14:37             ` Eli Zaretskii
2020-05-11 18:17         ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).