unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* "concurrency" branch updated
@ 2015-11-01  6:19 Ken Raeburn
  2015-11-02 17:09 ` Eli Zaretskii
  2015-11-02 20:23 ` John Wiegley
  0 siblings, 2 replies; 40+ messages in thread
From: Ken Raeburn @ 2015-11-01  6:19 UTC (permalink / raw)
  To: emacs-devel@gnu.org discussions

I’ve tried to get the concurrency branch updated with respect to master, including the handlerlist/catchlist merge and timerfd support. It seems to be working okay, passing the tests Tom checked it for it, and correctly running a few nice, simple tests that I tried. It also crashes on a not-so-nice, simple test I tried, but the old version did too. :-)

I dropped the changelogs. (Arguably maybe I should’ve pulled out just the branch-specific items and kept them?) I’ve tried to preserve the Windows-related changes, but not having a Windows box, I couldn’t test that part. I did some testing on Debian GNU/Linux and Mac OS X, but nothing fancy.

I haven’t done anything about addressing issues brought up a couple years back when this work was discussed here, but I’ve been starting to go back over some of those emails to see what’s needed.

Ken


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

* Re: "concurrency" branch updated
  2015-11-01  6:19 "concurrency" branch updated Ken Raeburn
@ 2015-11-02 17:09 ` Eli Zaretskii
  2015-11-02 20:23 ` John Wiegley
  1 sibling, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-02 17:09 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: emacs-devel

> From: Ken Raeburn <raeburn@raeburn.org>
> Date: Sun, 1 Nov 2015 01:19:38 -0500
> 
> I’ve tried to get the concurrency branch updated with respect to master, including the handlerlist/catchlist merge and timerfd support. It seems to be working okay, passing the tests Tom checked it for it, and correctly running a few nice, simple tests that I tried. It also crashes on a not-so-nice, simple test I tried, but the old version did too. :-)

Thanks for working on this.

> I dropped the changelogs. (Arguably maybe I should’ve pulled out just the branch-specific items and kept them?)

There should be no need, the log messages will provide that
information when we merge the branch.

> I’ve tried to preserve the Windows-related changes, but not having a Windows box, I couldn’t test that part.

The Windows build was broken, I fixed it.

> I haven’t done anything about addressing issues brought up a couple years back when this work was discussed here, but I’ve been starting to go back over some of those emails to see what’s needed.

Thanks!




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

* Re: "concurrency" branch updated
  2015-11-01  6:19 "concurrency" branch updated Ken Raeburn
  2015-11-02 17:09 ` Eli Zaretskii
@ 2015-11-02 20:23 ` John Wiegley
  2015-11-02 20:35   ` Eli Zaretskii
  2015-11-03  9:40   ` Ken Raeburn
  1 sibling, 2 replies; 40+ messages in thread
From: John Wiegley @ 2015-11-02 20:23 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: emacs-devel@gnu.org discussions

>>>>> Ken Raeburn <raeburn@raeburn.org> writes:

> I’ve tried to get the concurrency branch updated with respect to master,
> including the handlerlist/catchlist merge and timerfd support. It seems to
> be working okay, passing the tests Tom checked it for it, and correctly
> running a few nice, simple tests that I tried. It also crashes on a
> not-so-nice, simple test I tried, but the old version did too. :-)

Hi Ken,

I'm unfamiliar so far with the content of the concurrency branch, what changes
it makes, and the threading model it proposes.  Could you please summarize the
state of the art for me, so that I know what this branch entails?

Opening a general discussion about concurrency is something I'd like to do
soon, but not until I better understand what has already taken place.

Thank you,
  John



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

* Re: "concurrency" branch updated
  2015-11-02 20:23 ` John Wiegley
@ 2015-11-02 20:35   ` Eli Zaretskii
  2015-11-02 20:41     ` Eli Zaretskii
  2015-11-03  9:40   ` Ken Raeburn
  1 sibling, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-02 20:35 UTC (permalink / raw)
  To: John Wiegley; +Cc: raeburn, emacs-devel

> From: "John Wiegley" <johnw@newartisans.com>
> Date: Mon, 02 Nov 2015 15:23:33 -0500
> Cc: "emacs-devel@gnu.org discussions" <emacs-devel@gnu.org>
> 
> I'm unfamiliar so far with the content of the concurrency branch, what changes
> it makes, and the threading model it proposes.  Could you please summarize the
> state of the art for me, so that I know what this branch entails?
> 
> Opening a general discussion about concurrency is something I'd like to do
> soon, but not until I better understand what has already taken place.

Start here:

  http://lists.gnu.org/archive/html/emacs-devel/2012-08/msg00313.html

and continue here:

  http://lists.gnu.org/archive/html/emacs-devel/2013-08/msg00704.html

(the second thread goes on for 2 or 3 months).



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

* Re: "concurrency" branch updated
  2015-11-02 20:35   ` Eli Zaretskii
@ 2015-11-02 20:41     ` Eli Zaretskii
  2015-11-02 21:57       ` John Wiegley
  0 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-02 20:41 UTC (permalink / raw)
  To: johnw; +Cc: raeburn, emacs-devel

> Date: Mon, 02 Nov 2015 22:35:18 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: raeburn@raeburn.org, emacs-devel@gnu.org
> 
> Start here:
> 
>   http://lists.gnu.org/archive/html/emacs-devel/2012-08/msg00313.html
> 
> and continue here:
> 
>   http://lists.gnu.org/archive/html/emacs-devel/2013-08/msg00704.html
> 
> (the second thread goes on for 2 or 3 months).

Also, if you do

  git diff ...origin/concurrency

you will find among the changes a section for the ELisp manual that
describes the features on the Lisp level.  After that, src/thread.c,
src/systhread.c, and the rest of the C-level changes, for the gory
details.

Have fun!



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

* Re: "concurrency" branch updated
  2015-11-02 20:41     ` Eli Zaretskii
@ 2015-11-02 21:57       ` John Wiegley
  2015-11-03  3:58         ` Elias Mårtenson
  0 siblings, 1 reply; 40+ messages in thread
From: John Wiegley @ 2015-11-02 21:57 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: raeburn, emacs-devel

>>>>> Eli Zaretskii <eliz@gnu.org> writes:

> you will find among the changes a section for the ELisp manual that
> describes the features on the Lisp level. After that, src/thread.c,
> src/systhread.c, and the rest of the C-level changes, for the gory details.

> Have fun!

Thanks, Eli!  I will read through those carefully.

John



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

* Re: "concurrency" branch updated
  2015-11-02 21:57       ` John Wiegley
@ 2015-11-03  3:58         ` Elias Mårtenson
  2015-11-03  9:40           ` Ken Raeburn
  2015-11-03 16:23           ` Eli Zaretskii
  0 siblings, 2 replies; 40+ messages in thread
From: Elias Mårtenson @ 2015-11-03  3:58 UTC (permalink / raw)
  To: Eli Zaretskii, raeburn, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1271 bytes --]

I started playing around with this branch a bit and I quickly discovered an
issue. I wanted to take the opportunity of describing this issue while at
the same time hopefully gain some insight into the design of the feature.

What I did was to write the following function:

    (defun foo ()
      (loop for i from 0 below 10
            do (message (format "Message %d" i))
            do (sit-for 1)))

I then started this function in a thread:

    (make-thread #'foo)

What happened was that the 10 messages were printed to the *Messages*
buffer without any delay between them, and then the entire Emacs session
became incredibly sluggish.

Looking at the implementation of sit-for, it seems as though it ends up
calling read-event on a different thread which is probably not a good idea.
Is this a correct assessment?

Regards,
Elias

On 3 November 2015 at 05:57, John Wiegley <johnw@newartisans.com> wrote:

> >>>>> Eli Zaretskii <eliz@gnu.org> writes:
>
> > you will find among the changes a section for the ELisp manual that
> > describes the features on the Lisp level. After that, src/thread.c,
> > src/systhread.c, and the rest of the C-level changes, for the gory
> details.
>
> > Have fun!
>
> Thanks, Eli!  I will read through those carefully.
>
> John
>
>

[-- Attachment #2: Type: text/html, Size: 2279 bytes --]

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

* Re: "concurrency" branch updated
  2015-11-03  3:58         ` Elias Mårtenson
@ 2015-11-03  9:40           ` Ken Raeburn
  2015-11-03 16:26             ` Eli Zaretskii
  2015-11-03 16:23           ` Eli Zaretskii
  1 sibling, 1 reply; 40+ messages in thread
From: Ken Raeburn @ 2015-11-03  9:40 UTC (permalink / raw)
  To: Elias Mårtenson; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2521 bytes --]


> On Nov 2, 2015, at 22:58, Elias Mårtenson <lokedhs@gmail.com> wrote:
> 
> I started playing around with this branch a bit and I quickly discovered an issue. I wanted to take the opportunity of describing this issue while at the same time hopefully gain some insight into the design of the feature.
> 
> What I did was to write the following function:
> 
>     (defun foo ()
>       (loop for i from 0 below 10
>             do (message (format "Message %d" i))
>             do (sit-for 1)))
> 
> I then started this function in a thread:
> 
>     (make-thread #'foo)
> 
> What happened was that the 10 messages were printed to the *Messages* buffer without any delay between them, and then the entire Emacs session became incredibly sluggish.

Interesting… my use has been pretty minimal thus far, certainly not enough to be looking at performance issues. Though, I tried running your test case, and after displaying the messages, one per second, Emacs crashed! :-(

In my tests I’m usually running a pretty minimal environment — “emacs -Q”, no subprocesses or timers set up, Emacs should be basically quiescent when I’m not doing something to it. Could there have been any sort of input events pending (mouse motion, for example) that could cause it to skip the delay in sit-for in your test?

I do suspect that some things dealing with user input (reading, testing availability, even the flag indicating we’re waiting) might get confused in a multithreaded setup. The test I was using recently that reliably crashed Emacs was:

  (make-thread (lambda () (signal ‘foo nil)))

…though it has to be in an interactive Emacs, where the waiting_for_input flag can be set, which the “signal” routine really doesn’t like. Possibly waiting_for_input needs to be thread-local… or if it stays global, maybe Fsignal() just shouldn’t be looking at it any more.

A previous test which broke the pre-merged concurrency branch but which I haven’t tested recently was to create a thread and have it prompt for input… I think it was either yes-or-no-p or y-or-n-p; it seemed to put Emacs into a state where there were no key bindings, so it would complain about every character I typed.

So…yeah. Input seems to be a fragile area on the branch.

> Looking at the implementation of sit-for, it seems as though it ends up calling read-event on a different thread which is probably not a good idea. Is this a correct assessment?

Sounds about right to me, yes.

Ken

[-- Attachment #2: Type: text/html, Size: 4056 bytes --]

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

* Re: "concurrency" branch updated
  2015-11-02 20:23 ` John Wiegley
  2015-11-02 20:35   ` Eli Zaretskii
@ 2015-11-03  9:40   ` Ken Raeburn
  2015-11-03 11:50     ` other "concurrency" approaches Nic Ferrier
                       ` (2 more replies)
  1 sibling, 3 replies; 40+ messages in thread
From: Ken Raeburn @ 2015-11-03  9:40 UTC (permalink / raw)
  To: John Wiegley; +Cc: emacs-devel@gnu.org discussions

> I'm unfamiliar so far with the content of the concurrency branch, what changes
> it makes, and the threading model it proposes.  Could you please summarize the
> state of the art for me, so that I know what this branch entails?

The email threads that Eli pointed to are the best starting point. I’m doing some catching up myself; I haven’t worked on this branch until recently, though I've gotten a basic understanding of some of it through working on the merge.  I’ve got to dig through the emails from earlier reviews of the code and make some notes on things not yet done.  In addition to some proposed code changes, I’m sure at a minimum much more testing and bug fixing is needed, some assessment of the performance, and possibly some utility functions would be nice to have (e.g., mutex-try-lock, mutex-timed-wait).

At some point, we’ll want to demonstrate practical utility; not a trivial demo program that displays a few messages, and nothing on the scale of rewriting all of Gnus to be multithreaded, but somewhere in between.  I’m not sure what would be a good example.  A version of generator.el that uses threads instead of the CPS transformation of everything is a possibility, and it would probably simplify the writing and compiling of the generators, but it’d probably be more heavy-weight at run time.  Prefetching files’ contents, or searching already-loaded files, while tags-query-replace waits for the user to respond to a prompt?  Improving fontification somehow?

Concurrent execution of Lisp code is a way off, but IMHO a desirable thing to shoot for, if we want Emacs to get faster as machines go for multicore rather than faster clocks.  Currently, only one thread runs Lisp at a time, and switching can happen only at certain points (when explicitly requested, or when select is called), though I think we should try to expand that set of points.  Tom suggested possibly doing it periodically when we invoke the QUIT macro, which would include various points in the bytecode interpreter.

> Opening a general discussion about concurrency is something I'd like to do
> soon, but not until I better understand what has already taken place.

Understood.  I think there may also be places where we could use threads less visible to the Lisp world; TLS and redisplay come to mind.

Ken


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

* other "concurrency" approaches
  2015-11-03  9:40   ` Ken Raeburn
@ 2015-11-03 11:50     ` Nic Ferrier
  2015-11-03 15:44       ` Eli Zaretskii
  2015-11-03 15:14     ` "concurrency" branch updated Filipp Gunbin
  2015-11-03 16:29     ` Eli Zaretskii
  2 siblings, 1 reply; 40+ messages in thread
From: Nic Ferrier @ 2015-11-03 11:50 UTC (permalink / raw)
  To: emacs-devel@gnu.org discussions

While you are all talking about the concurrency branch I thought I'd
drop a line about other approaches that may be more tactical but would
be beneficial.

Some work has done by JohnW, others and myself on concurrency through
processes and the use of the existing process interface.

It's quite difficult to do this, but very beneficial. In effect what
we've been trying to do is emulate a fork model by just starting emacs
as a separate process. The fork approach to multiprocessing, while being
the tried and tested and perhaps rather old fashioned approach, has also
been very successful in modern languages like Python
(https://docs.python.org/2/library/multiprocessing.html).

In Emacs this is difficult because we don't have fork. And we don't have
a straight forward way of starting an Emacs process without a gui. You
can start a daemon, but daemons aren't what you want. In addition the
protocol for talking to daemons over sockets isn't that easy either.

Fork looks very hard to solve, in the same way that threads are quite
hard to solve.

But starting a headless Emacs, given that we have daemon already,
wouldn't be that hard.

What you want is the ability to do something like this:


 (let ((proc (start-process "emacs" args-to-make-it-headless)))
   (process-send-string proc (prin1-to-string '(+ 1 (* 30 45))))
   (process-send-eof proc)
   (print (buffer-string (process-buffer proc))))

in other words, an Emacs that just reads forms from stdin and executes
them and outputs to stdout.

The only complex thing here is how Emacs would understand that a form
has ended. I considered here just using end of line as the terminator
and if the form couldn't be read just issuing a read error. Other more
complex readers with a better line oriented UI might come later... but
for the use case of starting an Emacs from Emacs and communicating with
it it wouldn't be necessary.

Doing just this relatively small change would make an enormous
difference to building concurrency stuff in Emacs.


Nic



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

* Re: "concurrency" branch updated
  2015-11-03  9:40   ` Ken Raeburn
  2015-11-03 11:50     ` other "concurrency" approaches Nic Ferrier
@ 2015-11-03 15:14     ` Filipp Gunbin
  2015-11-03 15:35       ` Michael Albinus
  2015-11-03 16:29     ` Eli Zaretskii
  2 siblings, 1 reply; 40+ messages in thread
From: Filipp Gunbin @ 2015-11-03 15:14 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: John Wiegley, emacs-devel@gnu.org discussions

On 03/11/2015 04:40 -0500, Ken Raeburn wrote:

> At some point, we’ll want to demonstrate practical utility; not a
> trivial demo program that displays a few messages, and nothing on the
> scale of rewriting all of Gnus to be multithreaded, but somewhere in
> between.

Tramp operations or Gnus news retrieval in parallel thread would be
highly appreciated ;-)



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

* Re: "concurrency" branch updated
  2015-11-03 15:14     ` "concurrency" branch updated Filipp Gunbin
@ 2015-11-03 15:35       ` Michael Albinus
  2015-11-03 16:38         ` Thierry Volpiatto
  0 siblings, 1 reply; 40+ messages in thread
From: Michael Albinus @ 2015-11-03 15:35 UTC (permalink / raw)
  To: Filipp Gunbin; +Cc: John Wiegley, Ken Raeburn, emacs-devel@gnu.org discussions

Filipp Gunbin <fgunbin@fastmail.fm> writes:

>> At some point, we’ll want to demonstrate practical utility; not a
>> trivial demo program that displays a few messages, and nothing on the
>> scale of rewriting all of Gnus to be multithreaded, but somewhere in
>> between.
>
> Tramp operations or Gnus news retrieval in parallel thread would be
> highly appreciated ;-)

For Tramp, this has been discussed already in the past (and I did also
some experiments). Outcome in short: We would need new asynchronous
primitive file operations (or add an asynchronous flag to the existing
operations). Otherwise, it would break too many packages, which expect a
defined result of a file operation, when the function returns.

I would be happy to add asynchronous support to Tramp. After the design
has been fixed. `copy-file' might be a good candidate for a first shot.

See (info "(elisp) Magic File Names") for a complete list of primitive
functions supported by Tramp and other file name handlers.

Best regards, Michael.



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

* Re: other "concurrency" approaches
  2015-11-03 11:50     ` other "concurrency" approaches Nic Ferrier
@ 2015-11-03 15:44       ` Eli Zaretskii
  2015-11-03 17:16         ` Nic Ferrier
  0 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-03 15:44 UTC (permalink / raw)
  To: Nic Ferrier; +Cc: emacs-devel

> From: Nic Ferrier <nferrier@ferrier.me.uk>
> Date: Tue, 03 Nov 2015 11:50:37 +0000
> 
> Fork looks very hard to solve, in the same way that threads are quite
> hard to solve.
> 
> But starting a headless Emacs, given that we have daemon already,
> wouldn't be that hard.

What is a "headless Emacs"?

> What you want is the ability to do something like this:
> 
> 
>  (let ((proc (start-process "emacs" args-to-make-it-headless)))
>    (process-send-string proc (prin1-to-string '(+ 1 (* 30 45))))
>    (process-send-eof proc)
>    (print (buffer-string (process-buffer proc))))
> 
> in other words, an Emacs that just reads forms from stdin and executes
> them and outputs to stdout.

This sounds like a description of -batch, but you already know about
it, so I'm quite sure I'm missing something important here.



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

* Re: "concurrency" branch updated
  2015-11-03  3:58         ` Elias Mårtenson
  2015-11-03  9:40           ` Ken Raeburn
@ 2015-11-03 16:23           ` Eli Zaretskii
  1 sibling, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-03 16:23 UTC (permalink / raw)
  To: Elias Mårtenson; +Cc: raeburn, emacs-devel

> Date: Tue, 3 Nov 2015 11:58:19 +0800
> From: Elias Mårtenson <lokedhs@gmail.com>
> 
> I started playing around with this branch a bit and I quickly discovered an
> issue.

If you have read the discussions to which I pointed, you know that
this branch is not yet ready for play.

> I wanted to take the opportunity of describing this issue while at the
> same time hopefully gain some insight into the design of the feature.
> 
> What I did was to write the following function:
> 
> (defun foo ()
> (loop for i from 0 below 10
> do (message (format "Message %d" i))
> do (sit-for 1)))
> 
> I then started this function in a thread:
> 
> (make-thread #'foo)
> 
> What happened was that the 10 messages were printed to the *Messages* buffer
> without any delay between them, and then the entire Emacs session became
> incredibly sluggish.

This works for me, at least in "emacs -Q".  I don't see any of the
abnormal behavior you describe.  Did you try in "emacs -Q"?

> Looking at the implementation of sit-for, it seems as though it ends up calling
> read-event on a different thread which is probably not a good idea.

How do you see that?

When I run your program under GDB, I see only one announcement of a
new thread, when I evaluate the call to make-thread.  Then I see a
single announcement of thread exit, when the thread finishes counting
to 10.  I see no additional threads.

In general, it would make very little sense for sit-for and/or
read-event to start a new thread and run there, for fairly obvious
reasons.  What can happen when you call sit-for is a switch to
another thread, if there is one.  But in this case, I don't expect
that to happen.




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

* Re: "concurrency" branch updated
  2015-11-03  9:40           ` Ken Raeburn
@ 2015-11-03 16:26             ` Eli Zaretskii
  0 siblings, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-03 16:26 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: lokedhs, emacs-devel

> From: Ken Raeburn <raeburn@raeburn.org>
> Date: Tue, 3 Nov 2015 04:40:11 -0500
> Cc: emacs-devel <emacs-devel@gnu.org>
> 
> I do suspect that some things dealing with user input (reading, testing
> availability, even the flag indicating we’re waiting) might get confused in a
> multithreaded setup. The test I was using recently that reliably crashed Emacs
> was:
> 
> (make-thread (lambda () (signal ‘foo nil)))
> 
> …though it has to be in an interactive Emacs, where the waiting_for_input flag
> can be set, which the “signal” routine really doesn’t like. Possibly
> waiting_for_input needs to be thread-local… or if it stays global, maybe
> Fsignal() just shouldn’t be looking at it any more.
> 
> A previous test which broke the pre-merged concurrency branch but which I
> haven’t tested recently was to create a thread and have it prompt for input… I
> think it was either yes-or-no-p or y-or-n-p; it seemed to put Emacs into a
> state where there were no key bindings, so it would complain about every
> character I typed.
> 
> So…yeah. Input seems to be a fragile area on the branch.

IMO, the concurrency branch needs someone motivated enough and with
enough resources to work on it, before it will be ready for prime
time.  Ideally, that should be Tom, but we can only hope he will find
time for that.  If not, then someone else.  I don't see how this could
be moved forward without some non-trivial effort.  The design is
simple and robust, and the implementation fairly simple and easy to
understand.  What's needed, IMO, is a lot of testing and debugging,
and quite a lot of the latter on the C level.




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

* Re: "concurrency" branch updated
  2015-11-03  9:40   ` Ken Raeburn
  2015-11-03 11:50     ` other "concurrency" approaches Nic Ferrier
  2015-11-03 15:14     ` "concurrency" branch updated Filipp Gunbin
@ 2015-11-03 16:29     ` Eli Zaretskii
  2015-11-04  9:20       ` Ken Raeburn
  2 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-03 16:29 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: johnw, emacs-devel

> From: Ken Raeburn <raeburn@raeburn.org>
> Date: Tue, 3 Nov 2015 04:40:25 -0500
> Cc: "emacs-devel@gnu.org discussions" <emacs-devel@gnu.org>
> 
> At some point, we’ll want to demonstrate practical utility; not a trivial demo program that displays a few messages, and nothing on the scale of rewriting all of Gnus to be multithreaded, but somewhere in between.  I’m not sure what would be a good example.  A version of generator.el that uses threads instead of the CPS transformation of everything is a possibility, and it would probably simplify the writing and compiling of the generators, but it’d probably be more heavy-weight at run time.  Prefetching files’ contents, or searching already-loaded files, while tags-query-replace waits for the user to respond to a prompt?  Improving fontification somehow?

Given that only one thread can run Lisp, is the above even possible?

> Understood.  I think there may also be places where we could use threads less visible to the Lisp world; TLS and redisplay come to mind.

Given the general model-view-controller design of Emacs and the
structure of its main loop, is making redisplay run in a separate
thread really viable?




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

* Re: "concurrency" branch updated
  2015-11-03 15:35       ` Michael Albinus
@ 2015-11-03 16:38         ` Thierry Volpiatto
  0 siblings, 0 replies; 40+ messages in thread
From: Thierry Volpiatto @ 2015-11-03 16:38 UTC (permalink / raw)
  To: emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Filipp Gunbin <fgunbin@fastmail.fm> writes:
>
>>> At some point, we’ll want to demonstrate practical utility; not a
>>> trivial demo program that displays a few messages, and nothing on the
>>> scale of rewriting all of Gnus to be multithreaded, but somewhere in
>>> between.
>>
>> Tramp operations or Gnus news retrieval in parallel thread would be
>> highly appreciated ;-)
>
> For Tramp, this has been discussed already in the past (and I did also
> some experiments). Outcome in short: We would need new asynchronous
> primitive file operations (or add an asynchronous flag to the existing
> operations). Otherwise, it would break too many packages, which expect a
> defined result of a file operation, when the function returns.
>
> I would be happy to add asynchronous support to Tramp. After the design
> has been fixed. `copy-file' might be a good candidate for a first shot.

FYI async package is already able to copy remote files async from dired
or from helm.

-- 
Thierry




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

* Re: other "concurrency" approaches
  2015-11-03 15:44       ` Eli Zaretskii
@ 2015-11-03 17:16         ` Nic Ferrier
  2015-11-03 17:23           ` Eli Zaretskii
  0 siblings, 1 reply; 40+ messages in thread
From: Nic Ferrier @ 2015-11-03 17:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> What you want is the ability to do something like this:
>> 
>> 
>>  (let ((proc (start-process "emacs" args-to-make-it-headless)))
>>    (process-send-string proc (prin1-to-string '(+ 1 (* 30 45))))
>>    (process-send-eof proc)
>>    (print (buffer-string (process-buffer proc))))
>> 
>> in other words, an Emacs that just reads forms from stdin and executes
>> them and outputs to stdout.
>
> This sounds like a description of -batch, but you already know about
> it, so I'm quite sure I'm missing something important here.

-batch has a peculiar environment, it does not read the user's
environment.


Nic



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

* Re: other "concurrency" approaches
  2015-11-03 17:16         ` Nic Ferrier
@ 2015-11-03 17:23           ` Eli Zaretskii
  2015-11-03 22:28             ` Nic Ferrier
  0 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-03 17:23 UTC (permalink / raw)
  To: Nic Ferrier; +Cc: emacs-devel

> From: Nic Ferrier <nferrier@ferrier.me.uk>
> Cc: emacs-devel@gnu.org
> Date: Tue, 03 Nov 2015 17:16:10 +0000
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> >> What you want is the ability to do something like this:
> >> 
> >> 
> >>  (let ((proc (start-process "emacs" args-to-make-it-headless)))
> >>    (process-send-string proc (prin1-to-string '(+ 1 (* 30 45))))
> >>    (process-send-eof proc)
> >>    (print (buffer-string (process-buffer proc))))
> >> 
> >> in other words, an Emacs that just reads forms from stdin and executes
> >> them and outputs to stdout.
> >
> > This sounds like a description of -batch, but you already know about
> > it, so I'm quite sure I'm missing something important here.
> 
> -batch has a peculiar environment, it does not read the user's
> environment.

You mean, the init files?  But you can load them via -l, no?



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

* Re: other "concurrency" approaches
  2015-11-03 17:23           ` Eli Zaretskii
@ 2015-11-03 22:28             ` Nic Ferrier
  2015-11-04  3:48               ` Eli Zaretskii
  0 siblings, 1 reply; 40+ messages in thread
From: Nic Ferrier @ 2015-11-03 22:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Nic Ferrier <nferrier@ferrier.me.uk>
>> Cc: emacs-devel@gnu.org
>> Date: Tue, 03 Nov 2015 17:16:10 +0000
>> 
>> Eli Zaretskii <eliz@gnu.org> writes:
>> 
>> >> What you want is the ability to do something like this:
>> >> 
>> >> 
>> >>  (let ((proc (start-process "emacs" args-to-make-it-headless)))
>> >>    (process-send-string proc (prin1-to-string '(+ 1 (* 30 45))))
>> >>    (process-send-eof proc)
>> >>    (print (buffer-string (process-buffer proc))))
>> >> 
>> >> in other words, an Emacs that just reads forms from stdin and executes
>> >> them and outputs to stdout.
>> >
>> > This sounds like a description of -batch, but you already know about
>> > it, so I'm quite sure I'm missing something important here.
>> 
>> -batch has a peculiar environment, it does not read the user's
>> environment.
>
> You mean, the init files?  But you can load them via -l, no?

That fixes the init files but doesn't fix the environment. There are all
sorts of little things wrong.

There's also something wrong with stdin in that scenario as I recall.

Why don't you try it and see what I mean?



Nic



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

* Re: other "concurrency" approaches
  2015-11-03 22:28             ` Nic Ferrier
@ 2015-11-04  3:48               ` Eli Zaretskii
  0 siblings, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-04  3:48 UTC (permalink / raw)
  To: Nic Ferrier; +Cc: emacs-devel

> From: Nic Ferrier <nferrier@ferrier.me.uk>
> Cc: emacs-devel@gnu.org
> Date: Tue, 03 Nov 2015 22:28:03 +0000
> 
> >> -batch has a peculiar environment, it does not read the user's
> >> environment.
> >
> > You mean, the init files?  But you can load them via -l, no?
> 
> That fixes the init files but doesn't fix the environment. There are all
> sorts of little things wrong.

What is "environment" in this context?



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

* Re: "concurrency" branch updated
  2015-11-03 16:29     ` Eli Zaretskii
@ 2015-11-04  9:20       ` Ken Raeburn
  2015-11-04 15:40         ` Eli Zaretskii
                           ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: Ken Raeburn @ 2015-11-04  9:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: johnw, emacs-devel


> On Nov 3, 2015, at 11:29, Eli Zaretskii <eliz@gnu.org> wrote:
> 
>> From: Ken Raeburn <raeburn@raeburn.org>
>> Date: Tue, 3 Nov 2015 04:40:25 -0500
>> Cc: "emacs-devel@gnu.org discussions" <emacs-devel@gnu.org>
>> 
>> At some point, we’ll want to demonstrate practical utility; not a trivial demo program that displays a few messages, and nothing on the scale of rewriting all of Gnus to be multithreaded, but somewhere in between.  I’m not sure what would be a good example.  A version of generator.el that uses threads instead of the CPS transformation of everything is a possibility, and it would probably simplify the writing and compiling of the generators, but it’d probably be more heavy-weight at run time.  Prefetching files’ contents, or searching already-loaded files, while tags-query-replace waits for the user to respond to a prompt?  Improving fontification somehow?
> 
> Given that only one thread can run Lisp, is the above even possible?

Implementing a generator with a thread seems somewhat straightforward, needing some sort of simple communication channel between the main thread and the generator thread to pass “need next value” and “here’s the next value” messages back and forth; some extra work would be needed so that dropping all references to a generator makes everything, including the thread, go away.  Raising an error in the thread’s “yield” calls may be a way to tackle that, though it changes the semantics within the generator a bit.

For prefetching file contents or searching existing buffers, the “main” thread can release the global lock when it prompts for the user’s input, and a background thread can create buffers and load files, or search buffers for patterns, tossing results onto some sort of queue or other data structure for consumption by the main thread when it finishes with the file it’s on.

Inserting a file’s contents or searching a large buffer can take a long time, though, so these could make the interactive experience sluggish at times depending on what’s going on in background, unless we find a way to do some of these operations without holding the global lock.  (Aside: Has anyone thought about applying JIT native code generation or translation-to-C to regular expressions?)  And loading a file can prompt for local variable settings and such, which could get kind of confusing if mixed with tags-query-replace prompting relating to a different file, but refactoring insert-file-contents into a minimal file-reading routine that does no Lisp callbacks and another to deal with file name handlers and hooks and such could let us do the former on a helper thread and the latter (which could prompt the user) in the main thread at the expected time.

Both of those examples are mainly about running some extra work in the moments while we’re waiting for the user to respond to a prompt.  We may be able to do the same with idle timers or other such mechanisms.  In cases like that, I think it may come down to whether it’s easier and/or more maintainable to write code that cranks through the next step of an explicitly managed state machine, or structured code that maintains its state in program counters and variables local to each stack frame… sometimes it’s one, sometimes it’s the other.

As to fontification… I expect the code is pretty tight now, but maybe someone who knows that code has some insight into whether we could do it better with more CPU cores available.

So… yeah, I think some of them are possible, but I’m not sure any of them would be a particularly good way to show off.  Got any suggestions?


> 
>> Understood.  I think there may also be places where we could use threads less visible to the Lisp world; TLS and redisplay come to mind.
> 
> Given the general model-view-controller design of Emacs and the
> structure of its main loop, is making redisplay run in a separate
> thread really viable?

I’m not sure.  I’m not picturing redisplay running concurrently with Lisp so much as redisplay on display 1 running concurrently with redisplay on display 2, all happening at the same point in the code where we now run redisplay.  (Ignoring for the moment the bits where redisplay can trigger Lisp evaluation.)

Under X11 I doubt trying to process different frames on the same display in different threads would help at all, given that the data still all goes through one network connection.  I expect that display updates on Windows, being on the local machine, are fast enough that even if concurrent updates by two or more threads go faster than fully serialized updates, it wouldn’t make much difference in the user experience.  Though I am making some assumptions that redisplay isn’t doing many costly calculations compared to the cost of pushing the bits to the glass.

I suspect TLS is probably the more interesting case.

Ken


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

* Re: "concurrency" branch updated
  2015-11-04  9:20       ` Ken Raeburn
@ 2015-11-04 15:40         ` Eli Zaretskii
  2015-11-04 19:48           ` Ken Raeburn
  2015-11-04 23:09         ` Richard Stallman
  2015-11-05 21:46         ` Tom Tromey
  2 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-04 15:40 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: johnw, emacs-devel

> From: Ken Raeburn <raeburn@raeburn.org>
> Date: Wed, 4 Nov 2015 04:20:37 -0500
> Cc: johnw@newartisans.com,
>  emacs-devel@gnu.org
> 
> > On Nov 3, 2015, at 11:29, Eli Zaretskii <address@hidden> wrote:
> > 
> >> From: Ken Raeburn <address@hidden>
> >> Date: Tue, 3 Nov 2015 04:40:25 -0500
> >> Cc: "address@hidden discussions" <address@hidden>
> >> 
> >> At some point, we’ll want to demonstrate practical utility; not a trivial 
> >> demo program that displays a few messages, and nothing on the scale of 
> >> rewriting all of Gnus to be multithreaded, but somewhere in between.  I’m 
> >> not sure what would be a good example.  A version of generator.el that uses 
> >> threads instead of the CPS transformation of everything is a possibility, 
> >> and it would probably simplify the writing and compiling of the generators, 
> >> but it’d probably be more heavy-weight at run time.  Prefetching files’ 
> >> contents, or searching already-loaded files, while tags-query-replace waits 
> >> for the user to respond to a prompt?  Improving fontification somehow?
> > 
> > Given that only one thread can run Lisp, is the above even possible?
> 
> Implementing a generator with a thread seems somewhat straightforward, needing 
> some sort of simple communication channel between the main thread and the 
> generator thread to pass “need next value” and “here’s the next value” messages 
> back and forth; some extra work would be needed so that dropping all references 
> to a generator makes everything, including the thread, go away.  Raising an 
> error in the thread’s “yield” calls may be a way to tackle that, though it 
> changes the semantics within the generator a bit.

Both the generator and its consumer run Lisp, so they can only run in
sequence.  How is this different from running them both in a single
thread?

> For prefetching file contents or searching existing buffers, the “main” thread 
> can release the global lock when it prompts for the user’s input, and a 
> background thread can create buffers and load files, or search buffers for 
> patterns, tossing results onto some sort of queue or other data structure for 
> consumption by the main thread when it finishes with the file it’s on.

But then you are not talking about "normal" visiting of files or
searching of buffers.  You are talking about specialized features that
visit large number of files or are capable of somehow marking lots of
search hits for future presentation to users.  That is a far cry from
how we do this stuff currently -- you ask the user first, _then_ you
search or visit the file she asked for.

> refactoring insert-file-contents into a minimal file-reading routine
> that does no Lisp callbacks and another to deal with file name
> handlers and hooks and such could let us do the former on a helper
> thread and the latter (which could prompt the user) in the main
> thread at the expected time.

You are talking about some significant refactoring here, we currently
o all of this on the fly.  In any case, I can understand how this
would be a win with remote files, but with local files I'm quite sure
most of the time for inserting a file is taken by stuff like decoding
its contents, which we also do on the fly and which can call Lisp.
The I/O itself is quite fast nowadays, I think.  Just compare
insert-file-contents with insert-file-contents-literally for the same
large file, and see the big difference, especially if it includes some
non-ASCII text.

> Both of those examples are mainly about running some extra work in the moments 
> while we’re waiting for the user to respond to a prompt.  We may be able to do 
> the same with idle timers or other such mechanisms.  In cases like that, I 
> think it may come down to whether it’s easier and/or more maintainable to write 
> code that cranks through the next step of an explicitly managed state machine, 
> or structured code that maintains its state in program counters and variables 
> local to each stack frame… sometimes it’s one, sometimes it’s the other.
> 
> As to fontification… I expect the code is pretty tight now, but maybe someone 
> who knows that code has some insight into whether we could do it better with 
> more CPU cores available.
> 
> So… yeah, I think some of them are possible, but I’m not sure any of them would 
> be a particularly good way to show off.  Got any suggestions?

I think features that use timers, and idle timers in particular, are
natural candidates for using threads.  Stealth font-lock comes to
mind, for example.

> >> Understood.  I think there may also be places where we could use threads 
> >> less visible to the Lisp world; TLS and redisplay come to mind.
> > 
> > Given the general model-view-controller design of Emacs and the
> > structure of its main loop, is making redisplay run in a separate
> > thread really viable?
> 
> I’m not sure.  I’m not picturing redisplay running concurrently with Lisp so 
> much as redisplay on display 1 running concurrently with redisplay on display 
> 2, all happening at the same point in the code where we now run redisplay.  

Why is this use case important?  Do we really believe someone might
look at 2 different X displays at the same time?  Perhaps you meant
frames, not displays.  This could make a lot of sense, except that:

> (Ignoring for the moment the bits where redisplay can trigger Lisp evaluation.)

We cannot really ignore that, because this feature is used a lot.
However, the global lock will probably solve this.

A more problematic issue is that the display engine currently assumes
that (almost) nothing happens with buffers and strings while it does
its job.  If redisplay is multithreaded, we need to make sure no other
thread that can touch Lisp data could run.

> I am making some assumptions that redisplay isn’t doing many costly
> calculations compared to the cost of pushing the bits to the glass.

That's not really true, although the display engine tries very hard to
be very fast.  But I've seen cycles taking 10 msec and even 50 msec
(which already borders on crossing the annoyance threshold).  So there
are some pretty costly calculations during redisplay, which is why the
display engine is heavily optimized to avoid them as much as possible.

> I suspect TLS is probably the more interesting case.

What do we have in TLS that we don't have in any network connection?




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

* Re: "concurrency" branch updated
  2015-11-04 15:40         ` Eli Zaretskii
@ 2015-11-04 19:48           ` Ken Raeburn
  2015-11-04 20:51             ` Eli Zaretskii
  0 siblings, 1 reply; 40+ messages in thread
From: Ken Raeburn @ 2015-11-04 19:48 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: johnw, emacs-devel

>> 
>> Implementing a generator with a thread seems somewhat straightforward, needing 
>> some sort of simple communication channel between the main thread and the 
>> generator thread to pass “need next value” and “here’s the next value” messages 
>> back and forth; some extra work would be needed so that dropping all references 
>> to a generator makes everything, including the thread, go away.  Raising an 
>> error in the thread’s “yield” calls may be a way to tackle that, though it 
>> changes the semantics within the generator a bit.
> 
> Both the generator and its consumer run Lisp, so they can only run in
> sequence.  How is this different from running them both in a single
> thread?

In this case, it’s about how you'd write the generator code.  While the multithreaded version would have other issues (like having to properly quit the new thread when we’re done with the generator), it wouldn’t require writing everything using special macros to do CPS transformations.  If I want to yield values from within a function invoked via mapcar, I don’t have to write an iter-mapcar macro to turn everything inside-out under the covers.

> 
>> For prefetching file contents or searching existing buffers, the “main” thread 
>> can release the global lock when it prompts for the user’s input, and a 
>> background thread can create buffers and load files, or search buffers for 
>> patterns, tossing results onto some sort of queue or other data structure for 
>> consumption by the main thread when it finishes with the file it’s on.
> 
> But then you are not talking about "normal" visiting of files or
> searching of buffers.  You are talking about specialized features that
> visit large number of files or are capable of somehow marking lots of
> search hits for future presentation to users.  That is a far cry from
> how we do this stuff currently -- you ask the user first, _then_ you
> search or visit the file she asked for.

I haven’t used tags-query-replace in a while, but I don’t recall it asking me if I wanted to visit each file.  But yes, I’m thinking of larger operations where the next stage is fairly predictable, and probably does no harm if we optimistically start it early.  Smaller stuff may be good too (I hope), but I’d guess there’s a greater chance the thread-switching overhead could become an issue; I could well be overestimating it.  And some of the simpler ones, like highlighting all regexp matches in the visible part of the current buffer while doing a search, are already done, though we could look at how the code would compare if rewritten to use threads.


> You are talking about some significant refactoring here, we currently
> o all of this on the fly.  In any case, I can understand how this
> would be a win with remote files, but with local files I'm quite sure
> most of the time for inserting a file is taken by stuff like decoding
> its contents, which we also do on the fly and which can call Lisp.
> The I/O itself is quite fast nowadays, I think.  Just compare
> insert-file-contents with insert-file-contents-literally for the same
> large file, and see the big difference, especially if it includes some
> non-ASCII text.

I haven’t done that test, but I have used an NFS server that got slow at times.  And NFS from Amazon virtual machines back to my office, which is always a bit slow.  And sshfs, which can be slow too.  None of which Emacs can do anything about directly.

>> So… yeah, I think some of them are possible, but I’m not sure any of them would 
>> be a particularly good way to show off.  Got any suggestions?
> 
> I think features that use timers, and idle timers in particular, are
> natural candidates for using threads.  Stealth font-lock comes to
> mind, for example.

That’s what I was thinking of when I mentioned fontification.  I hope thread switches are fast enough.

>> I’m not sure.  I’m not picturing redisplay running concurrently with Lisp so 
>> much as redisplay on display 1 running concurrently with redisplay on display 
>> 2, all happening at the same point in the code where we now run redisplay.  
> 
> Why is this use case important?  Do we really believe someone might
> look at 2 different X displays at the same time?

No, but occasionally redisplay still needs to talk to multiple displays and get responses back, even with the work you and Stefan have done.  Fortunately, it’s much more rare now, and the color-handling work I did may help further.  And people using multiple displays *and* slow display connections like me are probably not very common among the user base.  So it’s an area where threads might help, but maybe not a terribly important one for the project.

>> I am making some assumptions that redisplay isn’t doing many costly
>> calculations compared to the cost of pushing the bits to the glass.
> 
> That's not really true, although the display engine tries very hard to
> be very fast.  But I've seen cycles taking 10 msec and even 50 msec
> (which already borders on crossing the annoyance threshold).  So there
> are some pretty costly calculations during redisplay, which is why the
> display engine is heavily optimized to avoid them as much as possible.

In that case, maybe it’s still worth considering after all.

> 
>> I suspect TLS is probably the more interesting case.
> 
> What do we have in TLS that we don't have in any network connection?

Encryption, optional compression, possibly key renegotiation, possible receipt of incomplete messages that can’t yet be decrypted and thus can’t give us any new data bytes.  The thread(s) running user Lisp code needn’t spend any cycles on these things.

Ken


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

* Re: "concurrency" branch updated
  2015-11-04 19:48           ` Ken Raeburn
@ 2015-11-04 20:51             ` Eli Zaretskii
  2015-11-05  5:16               ` Ken Raeburn
  0 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-04 20:51 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: johnw, emacs-devel

> From: Ken Raeburn <raeburn@raeburn.org>
> Date: Wed, 4 Nov 2015 14:48:12 -0500
> Cc: johnw@newartisans.com,
>  emacs-devel@gnu.org
> 
> >> I suspect TLS is probably the more interesting case.
> > 
> > What do we have in TLS that we don't have in any network connection?
> 
> Encryption, optional compression, possibly key renegotiation, possible receipt of incomplete messages that can’t yet be decrypted and thus can’t give us any new data bytes.

Doesn't all that become insignificant compared to network latencies?




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

* Re: "concurrency" branch updated
  2015-11-04  9:20       ` Ken Raeburn
  2015-11-04 15:40         ` Eli Zaretskii
@ 2015-11-04 23:09         ` Richard Stallman
  2015-11-05  3:41           ` Eli Zaretskii
                             ` (2 more replies)
  2015-11-05 21:46         ` Tom Tromey
  2 siblings, 3 replies; 40+ messages in thread
From: Richard Stallman @ 2015-11-04 23:09 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: johnw, eliz, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

We don't need radical changes such as CPS to implement concurrent Lisp.
All we need is multiple stacks.

It seems to me that in Emacs there is no need to be able to switch threads
except when a thread is waiting.  That should make things much simpler.

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




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

* Re: "concurrency" branch updated
  2015-11-04 23:09         ` Richard Stallman
@ 2015-11-05  3:41           ` Eli Zaretskii
  2015-11-05  6:29           ` Ken Raeburn
  2015-11-05 21:49           ` Tom Tromey
  2 siblings, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-05  3:41 UTC (permalink / raw)
  To: rms; +Cc: johnw, raeburn, emacs-devel

> From: Richard Stallman <rms@gnu.org>
> CC: eliz@gnu.org, johnw@newartisans.com, emacs-devel@gnu.org
> Date: Wed, 04 Nov 2015 18:09:32 -0500
> 
> It seems to me that in Emacs there is no need to be able to switch threads
> except when a thread is waiting.  That should make things much simpler.

That's what the concurrency branch does.



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

* Re: "concurrency" branch updated
  2015-11-04 20:51             ` Eli Zaretskii
@ 2015-11-05  5:16               ` Ken Raeburn
  0 siblings, 0 replies; 40+ messages in thread
From: Ken Raeburn @ 2015-11-05  5:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: johnw, emacs-devel

>>> What do we have in TLS that we don't have in any network connection?
>> 
>> Encryption, optional compression, possibly key renegotiation, possible receipt of incomplete messages that can’t yet be decrypted and thus can’t give us any new data bytes.
> 
> Doesn't all that become insignificant compared to network latencies?

Not if I’m requesting a large amount of data from the server at once, or pipelining requests, or talking to multiple servers at once; I could have a steady stream of encrypted data coming in, and the latency from making a particular request to getting the corresponding response may not be important.

Whether the bandwidth available is enough that decrypting plus parsing (assuming we’re encrypting some network protocol and not an opaque file transfer) plus updating data structures plus UI updates plus the occasional GC is more than one thread can keep up with, that’s the question….  With additional C-level threads for managing TLS connections, we can at least take the decryption part out of that list and run it concurrently, without needing full Lisp-level thread support.

Ken


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

* Re: "concurrency" branch updated
  2015-11-04 23:09         ` Richard Stallman
  2015-11-05  3:41           ` Eli Zaretskii
@ 2015-11-05  6:29           ` Ken Raeburn
  2015-11-05 13:17             ` John Wiegley
  2015-11-05 22:46             ` Richard Stallman
  2015-11-05 21:49           ` Tom Tromey
  2 siblings, 2 replies; 40+ messages in thread
From: Ken Raeburn @ 2015-11-05  6:29 UTC (permalink / raw)
  To: rms; +Cc: johnw, eliz, emacs-devel

> It seems to me that in Emacs there is no need to be able to switch threads
> except when a thread is waiting.  That should make things much simpler.

Simpler, yes, but also more limiting.  Any large computational task needs to be written to surrender control now and then, if it might be used in an Emacs session that also talks to network servers that may time out and close connections if Emacs ignores them for too long.  I’ve had that happen.  Long delays waiting on a file system read operation (from NFS server or network hiccups) can have a similar effect, though we can probably arrange for some file operations to permit switching even if they’re normally quite fast.

I think preemptive thread switching (or real concurrent execution) is a better place to wind up, but cooperative thread switching is a good start.

Ken


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

* Re: "concurrency" branch updated
  2015-11-05  6:29           ` Ken Raeburn
@ 2015-11-05 13:17             ` John Wiegley
  2015-11-05 14:17               ` David Kastrup
  2015-11-05 21:55               ` Tom Tromey
  2015-11-05 22:46             ` Richard Stallman
  1 sibling, 2 replies; 40+ messages in thread
From: John Wiegley @ 2015-11-05 13:17 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: eliz, rms, emacs-devel

>>>>> Ken Raeburn <raeburn@raeburn.org> writes:

>> It seems to me that in Emacs there is no need to be able to switch threads
>> except when a thread is waiting. That should make things much simpler.

> I think preemptive thread switching (or real concurrent execution) is a
> better place to wind up, but cooperative thread switching is a good start.

I haven't had a chance to read this entire thread yet, but I wanted to chime
in and agree with both Richard and Ken. I have relatively few fears about
cooperative thread switching. Also, it gives us a chance to see how people
deal with debugging the sorts of issues it can lead to (e.g., a backtrace from
code unrelated to something you think you just did).

Upgrading to preemptive switching could happen later, once we've had more
experience with writing cooperative code. I hope at that point it would be a
fairly seamless upgrade, and we'd have mature facilities in place to
accommodate it (i.e., the ability to "stack" backtraces, to inspect the
environment of inactive threads, a messaging facility between threads to avoid
global mutation, etc).

What I want most is to make deadlocks and race conditions naturally hard to
write -- if not impossible. The rise of Heisenbugs could make our job as
maintainers much more difficult. All the worst bugs in my programming career
were related to preemptive threading in some way.

John



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

* Re: "concurrency" branch updated
  2015-11-05 13:17             ` John Wiegley
@ 2015-11-05 14:17               ` David Kastrup
  2015-11-05 15:07                 ` John Wiegley
  2015-11-05 21:55               ` Tom Tromey
  1 sibling, 1 reply; 40+ messages in thread
From: David Kastrup @ 2015-11-05 14:17 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: eliz, rms, emacs-devel

John Wiegley <johnw@newartisans.com> writes:

>>>>>> Ken Raeburn <raeburn@raeburn.org> writes:
>
>>> It seems to me that in Emacs there is no need to be able to switch threads
>>> except when a thread is waiting. That should make things much simpler.
>
>> I think preemptive thread switching (or real concurrent execution) is a
>> better place to wind up, but cooperative thread switching is a good start.
>
> I haven't had a chance to read this entire thread yet, but I wanted to chime
> in and agree with both Richard and Ken. I have relatively few fears about
> cooperative thread switching. Also, it gives us a chance to see how people
> deal with debugging the sorts of issues it can lead to (e.g., a backtrace from
> code unrelated to something you think you just did).
>
> Upgrading to preemptive switching could happen later, once we've had more
> experience with writing cooperative code.

It depends on what "upgrading" means.  For example, Lua offers
"coroutines" which are basically not more than independent stacks but
not parallel execution: the corresponding functions, "yield" and
"resume" both _take_ and _return_ values.  Essentially, this is used as
a control flow mechanism similar to function calls and returns, with the
difference that such "functions" do not lose their place and local
variables when "returning" but continue upon resuming.

Since the switching of threads is accompanied by a passing of values,
executing such threads in parallel is not an option and thus there are
no concurrency issues.

I've used this kind of control flow (basically swapping in a different
stack and returning) in terminal emulators written in assembly language
to good effect: code becomes much more readable if the various code
paths interpreting terminal control sequences can just "call" the user
program for additional characters (where "call" means returning to the
user program and laying dormant until the terminal emulator gets called
with the next character) without losing the place in the logic of the
terminal emulator.

This kind of stack swap is not the same as true multithreading.  It
definitely has interesting applications with regard to things like
generators and streams as it may lead to much more straightforward code
than trying to maintain some internal state in closure variables queried
on reentry when the most natural representation of the internal state
you'd want to maintain is the current instruction and stack pointer.

I think Ada has the concept of "rendezvous" for multithreading where
there are well-defined synchronous parts of interaction as well as
asynchronous execution.

> I hope at that point it would be a fairly seamless upgrade,

For some kinds of control flow application, parallelism might not even
be an option.

-- 
David Kastrup



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

* Re: "concurrency" branch updated
  2015-11-05 14:17               ` David Kastrup
@ 2015-11-05 15:07                 ` John Wiegley
  0 siblings, 0 replies; 40+ messages in thread
From: John Wiegley @ 2015-11-05 15:07 UTC (permalink / raw)
  To: David Kastrup; +Cc: eliz, Ken Raeburn, rms, emacs-devel

>>>>> David Kastrup <dak@gnu.org> writes:

> For example, Lua offers "coroutines" which are basically not more than
> independent stacks but not parallel execution: the corresponding functions,
> "yield" and "resume" both _take_ and _return_ values. Essentially, this is
> used as a control flow mechanism similar to function calls and returns, with
> the difference that such "functions" do not lose their place and local
> variables when "returning" but continue upon resuming.

What you describe sounds similar to several libraries used often in Haskell,
where continuations are used to shuttle control up and down a connected
pipeline of coordinated functions (see 'pipes' if interested). Parallel
execution cannot be automatically enabled there either, though it can be
injected between stages (see 'pipes-async').

John



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

* Re: "concurrency" branch updated
  2015-11-04  9:20       ` Ken Raeburn
  2015-11-04 15:40         ` Eli Zaretskii
  2015-11-04 23:09         ` Richard Stallman
@ 2015-11-05 21:46         ` Tom Tromey
  2015-11-06  7:58           ` Eli Zaretskii
  2 siblings, 1 reply; 40+ messages in thread
From: Tom Tromey @ 2015-11-05 21:46 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: johnw, Eli Zaretskii, emacs-devel

Ken> So… yeah, I think some of them are possible, but I’m not sure any of
Ken> them would be a particularly good way to show off.  Got any
Ken> suggestions?

One idea would be to make it so that each terminal runs in its own
thread.  Maybe whatever accepts new connections from emacsclient could
also have its own thread as well.

This way connecting to Emacs from a tty could still work even if the X
frame is busy working (provided of course that the Lisp that is working
would yield periodically; but that is a good idea anyway for I/O).

Tom



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

* Re: "concurrency" branch updated
  2015-11-04 23:09         ` Richard Stallman
  2015-11-05  3:41           ` Eli Zaretskii
  2015-11-05  6:29           ` Ken Raeburn
@ 2015-11-05 21:49           ` Tom Tromey
  2 siblings, 0 replies; 40+ messages in thread
From: Tom Tromey @ 2015-11-05 21:49 UTC (permalink / raw)
  To: Richard Stallman; +Cc: johnw, eliz, Ken Raeburn, emacs-devel

RMS> We don't need radical changes such as CPS to implement concurrent Lisp.
RMS> All we need is multiple stacks.

This is what is done on the branch.

RMS> It seems to me that in Emacs there is no need to be able to switch threads
RMS> except when a thread is waiting.  That should make things much simpler.

This is also what is implemented.

However, it's better to eventually yield the global lock periodically in
somewhere (maybe QUIT, but that might be trouble), so that threads don't
have to explicitly yield.  FWIW this is what Python does.

Tom



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

* Re: "concurrency" branch updated
  2015-11-05 13:17             ` John Wiegley
  2015-11-05 14:17               ` David Kastrup
@ 2015-11-05 21:55               ` Tom Tromey
  2015-11-05 22:01                 ` John Wiegley
  1 sibling, 1 reply; 40+ messages in thread
From: Tom Tromey @ 2015-11-05 21:55 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: eliz, rms, emacs-devel

John> Upgrading to preemptive switching could happen later, once we've
John> had more experience with writing cooperative code. I hope at that
John> point it would be a fairly seamless upgrade, and we'd have mature
John> facilities in place to accommodate it (i.e., the ability to
John> "stack" backtraces, to inspect the environment of inactive
John> threads, a messaging facility between threads to avoid global
John> mutation, etc).

I don't understand what stacking backtraces is.

Messaging is already on the branch; or rather, locks and condition
variables are on the branch, and it's simple to build thread-safe pipes
and queues and whatnot using those.

John> What I want most is to make deadlocks and race conditions
John> naturally hard to write -- if not impossible. The rise of
John> Heisenbugs could make our job as maintainers much more
John> difficult. All the worst bugs in my programming career were
John> related to preemptive threading in some way.

Race-free-ness will not come from this branch.  It takes a traditional
threads-and-locks approach.

Tom



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

* Re: "concurrency" branch updated
  2015-11-05 21:55               ` Tom Tromey
@ 2015-11-05 22:01                 ` John Wiegley
  0 siblings, 0 replies; 40+ messages in thread
From: John Wiegley @ 2015-11-05 22:01 UTC (permalink / raw)
  To: Tom Tromey; +Cc: eliz, Ken Raeburn, rms, emacs-devel

>>>>> Tom Tromey <tom@tromey.com> writes:

> I don't understand what stacking backtraces is.

When a signal occurs while you're already looking at a backtrace.

> Messaging is already on the branch; or rather, locks and condition variables
> are on the branch, and it's simple to build thread-safe pipes and queues and
> whatnot using those.

I definitely need to examine your previous work before saying more. :)

John> What I want most is to make deadlocks and race conditions
John> naturally hard to write -- if not impossible. The rise of
John> Heisenbugs could make our job as maintainers much more
John> difficult. All the worst bugs in my programming career were
John> related to preemptive threading in some way.

> Race-free-ness will not come from this branch. It takes a traditional
> threads-and-locks approach.

This is definitely an area for further discussion; though that shouldn't stop
us from continuing to think about the cooperative approach.

John



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

* Re: "concurrency" branch updated
  2015-11-05  6:29           ` Ken Raeburn
  2015-11-05 13:17             ` John Wiegley
@ 2015-11-05 22:46             ` Richard Stallman
  2015-11-06  8:37               ` Eli Zaretskii
  1 sibling, 1 reply; 40+ messages in thread
From: Richard Stallman @ 2015-11-05 22:46 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: johnw, eliz, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

    > Any large computational task needs to be written to surrender control now and then, if it might be used in an Emacs session that also talks to network servers that may time out and close connections if Emacs ignores them for too long.

It is easy to make a function that offers to switch threads.

    > Long delays waiting on a file system read operation (from NFS
    > server or network hiccups) can have a similar effect, though we
    > can probably arrange for some file operations to permit
    > switching even if they’re normally quite fast.

We might want those to be treated as waiting -- for instance, to handle
them through something more like tramp.


-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




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

* Re: "concurrency" branch updated
  2015-11-05 21:46         ` Tom Tromey
@ 2015-11-06  7:58           ` Eli Zaretskii
  2015-11-06 14:58             ` Tom Tromey
  0 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-06  7:58 UTC (permalink / raw)
  To: Tom Tromey; +Cc: johnw, raeburn, emacs-devel

> From: Tom Tromey <tom@tromey.com>
> Cc: Eli Zaretskii <eliz@gnu.org>,  johnw@newartisans.com,  emacs-devel@gnu.org
> Date: Thu, 05 Nov 2015 14:46:40 -0700
> 
> One idea would be to make it so that each terminal runs in its own
> thread.

By "terminal" do you mean X display?  If so, the w32 port already does
something like that: it reads system input messages, including
keyboard input and all the rest, in a separate thread, which feeds the
queue serviced by the read_socket hook.



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

* Re: "concurrency" branch updated
  2015-11-05 22:46             ` Richard Stallman
@ 2015-11-06  8:37               ` Eli Zaretskii
  0 siblings, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2015-11-06  8:37 UTC (permalink / raw)
  To: rms; +Cc: johnw, raeburn, emacs-devel

> From: Richard Stallman <rms@gnu.org>
> CC: johnw@newartisans.com, eliz@gnu.org, emacs-devel@gnu.org
> Date: Thu, 05 Nov 2015 17:46:29 -0500
> 
>     > Any large computational task needs to be written to surrender control now and then, if it might be used in an Emacs session that also talks to network servers that may time out and close connections if Emacs ignores them for too long.
> 
> It is easy to make a function that offers to switch threads.

Tom already wrote it, and it is part of the code on the branch.  It's
called 'thread-yield', not surprisingly.



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

* Re: "concurrency" branch updated
  2015-11-06  7:58           ` Eli Zaretskii
@ 2015-11-06 14:58             ` Tom Tromey
  0 siblings, 0 replies; 40+ messages in thread
From: Tom Tromey @ 2015-11-06 14:58 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: johnw, Tom Tromey, raeburn, emacs-devel

>> One idea would be to make it so that each terminal runs in its own
>> thread.

Eli> By "terminal" do you mean X display?  If so, the w32 port already does
Eli> something like that: it reads system input messages, including
Eli> keyboard input and all the rest, in a separate thread, which feeds the
Eli> queue serviced by the read_socket hook.

Yeah, basically each thing with its own conceptual input queue; so each
X connection but also each tty frame.

Tom



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

end of thread, other threads:[~2015-11-06 14:58 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-01  6:19 "concurrency" branch updated Ken Raeburn
2015-11-02 17:09 ` Eli Zaretskii
2015-11-02 20:23 ` John Wiegley
2015-11-02 20:35   ` Eli Zaretskii
2015-11-02 20:41     ` Eli Zaretskii
2015-11-02 21:57       ` John Wiegley
2015-11-03  3:58         ` Elias Mårtenson
2015-11-03  9:40           ` Ken Raeburn
2015-11-03 16:26             ` Eli Zaretskii
2015-11-03 16:23           ` Eli Zaretskii
2015-11-03  9:40   ` Ken Raeburn
2015-11-03 11:50     ` other "concurrency" approaches Nic Ferrier
2015-11-03 15:44       ` Eli Zaretskii
2015-11-03 17:16         ` Nic Ferrier
2015-11-03 17:23           ` Eli Zaretskii
2015-11-03 22:28             ` Nic Ferrier
2015-11-04  3:48               ` Eli Zaretskii
2015-11-03 15:14     ` "concurrency" branch updated Filipp Gunbin
2015-11-03 15:35       ` Michael Albinus
2015-11-03 16:38         ` Thierry Volpiatto
2015-11-03 16:29     ` Eli Zaretskii
2015-11-04  9:20       ` Ken Raeburn
2015-11-04 15:40         ` Eli Zaretskii
2015-11-04 19:48           ` Ken Raeburn
2015-11-04 20:51             ` Eli Zaretskii
2015-11-05  5:16               ` Ken Raeburn
2015-11-04 23:09         ` Richard Stallman
2015-11-05  3:41           ` Eli Zaretskii
2015-11-05  6:29           ` Ken Raeburn
2015-11-05 13:17             ` John Wiegley
2015-11-05 14:17               ` David Kastrup
2015-11-05 15:07                 ` John Wiegley
2015-11-05 21:55               ` Tom Tromey
2015-11-05 22:01                 ` John Wiegley
2015-11-05 22:46             ` Richard Stallman
2015-11-06  8:37               ` Eli Zaretskii
2015-11-05 21:49           ` Tom Tromey
2015-11-05 21:46         ` Tom Tromey
2015-11-06  7:58           ` Eli Zaretskii
2015-11-06 14:58             ` Tom Tromey

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).