run-with-timer vs run-with-idle-timer
(too old to reply)
Thien-Thi Nguyen
2018-05-12 17:37:45 UTC
() João Távora <***@gmail.com>
() Fri, 11 May 2018 11:39:16 +0100

After thinking a bit about it, you're totally right, and it
becomes much simpler (read below).

Cool, simpler (if it still works) is better.
I suppose it's a matter of style.
Maybe not, maybe [while CONDITION] is indeed more efficient,
since it amounts to far fewer calls to accept-process-output.

It's less efficient up until the point CONDITION is no longer
satisfied (since it has to compute/check CONDITION). But past
that point, it's infinitely more efficient for the reason you
able to play multiple games simultaneously (i.e., run
multiple independent child processes), and greedily
spinning borks that.
Since from Emacs's perspective we're both blocking, you must
mean that you have less CPU available for the subprocesses,

I don't really know what i meant, actually. I think it was just
my ego trying to sound bigger than my memory would permit. You
will forgive the fool curmudgeon a lapse here and there, right?
It's been a long time since i used the verb "bork"... /pleading

The truth is that ‘gnugo--q’ is synchronous by design (it says
so right in the comment about ‘:srs’, after all -- but who reads
comments, anyway?!) and does indeed block (since 1st arg to
‘accept-process-output’ is specified) until input appears.

That said, top-level (user interaction) control only passes to
‘gnugo--q’ via ‘run-at-time’, which normally fires after two
seconds, plenty of time (even on this old computer) for Emacs to
move its pointers around. Too, because the action is captured
in a timer object, Emacs has even more of a free hand to diddle
w/ its scheduling. To sum up, spinning is what is going on,
true, but "greedily" maybe not so much. Really, it's more like
bowing to the four corners of the earth (once) than spinning...
[...] seeing a skeleton of the code [...]
If you haven't yet connected the dots, this is for my new
mode eglot.el from the other thread.

Ah OK. Sounds interesting!

Since it is very new, I think I'm just going to apply your
suggestion (diff below).


It works fine and the code becomes tighter, though it still
doesn't solve the original problem that makes the idle-timer
not kick in in the meantime. (Later, I can explain more
about why I need that, and how I'm working around it).

Thien-Thi Nguyen -----------------------------------------------
(defun responsep (query)
(pcase (context query)
(`(technical ,ml) (correctp ml))
...)) 748E A0E8 1CB8 A748 9BFA
--------------------------------------- 6CE4 6703 2224 4C80 7502
Thien-Thi Nguyen
2018-05-12 17:57:43 UTC
() João Távora <***@gmail.com>
() Fri, 11 May 2018 12:05:48 +0100
I suppose it's a matter of style.
Just to clarify, since I've just realised we're talking about
two independent things here:

1. "catch/loop/throw" vs "let/test/loop/set" is indeed a
matter of style (but you've probably convinced me to
prefer the latter).

Yeah, that was my meaning. I look forward to learning why
‘run-with-idle-timer’ is even necessary (my only experience w/
that is in zone.el func ‘zone-when-idle’).

2. It's the short timeout to accept-process-output that I'm
supposing hurts performance, but it can also be lengthened
using the first idiom.

Why does a short timeout hurt performance? My understanding is:
large timeout => more time for subproc to do its thing => bigger
and fewer chunks of input => less overhead relatively => better
overall performance.

[timeout value gyrations]

Sounds somewhat cargo-cult. Just like Emacs, i suppose... :-D
Thien-Thi Nguyen -----------------------------------------------
(defun responsep (query)
(pcase (context query)
(`(technical ,ml) (correctp ml))
...)) 748E A0E8 1CB8 A748 9BFA
--------------------------------------- 6CE4 6703 2224 4C80 7502
João Távora
2018-05-09 20:18:02 UTC
An idle timer set for 600 seconds will run when ten minutes have
elapsed since the last user command was finished, even if subprocess
output has been accepted thousands of times within those ten minutes,
and even if there have been garbage collections and autosaves.
Doesn't this contradict what you told me first? I.e doesn't this
contradict the fact that this never returns?
(catch 'done
(run-with-idle-timer 600 nil (lambda () (throw 'done nil)))
(while t (accept-process-output nil 0.1))) ; 6 thousand times
or should the manual be saying "even if subprocesses output has been
non-explictly accepted thousands of times"?
No, because whatever command you used to invoke that code (C-x C-e in the
trivial case) doesn't finish unless and until the loop finishes. So no
time has yet "elapsed since the last user command was finished", regardless
of anything about subprocesses.


1 nil
(lambda ()
(catch 'done
(run-with-idle-timer 3 nil (lambda () (throw 'done nil)))
(while t (accept-process-output nil 0.1)))
(message "ok!")))

Does print "ok". However this blocks typing for 3 seconds. So in a way,
it forces idleness. Gross idea anyway. Wonder what happens in the filter...