unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Experiment with threads - no concurrency?
@ 2021-09-06 14:35 Arthur Miller
  2021-09-06 15:17 ` Stefan Monnier
  2021-09-06 15:47 ` Eli Zaretskii
  0 siblings, 2 replies; 10+ messages in thread
From: Arthur Miller @ 2021-09-06 14:35 UTC (permalink / raw)
  To: emacs-devel

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


I did a little experiment today. I wanted to count frequency of Emacs functions
usage. So I started by indexing all functions and macros.

Since it is kind of lot's of I/O and independent tasks to do, I thought threads
could come handy. However I see no difference from sequential code.

I tried different versions, one where I did a single call to
directory-files-recursively, and than used one thread per file, to parse each
file separately, in own thread, but it was the slowest version. When I used to
code in Java long time ago, I used to see improvement in this kind of jobs due
to I/O. Maybe I am missunderstanding Emacs threads here?

In second version, I do two calls to directory-files-recursively, each in it's
own thread and use only two threads to do all the work, one per list. It is
slightly faster, but just slightly and still slower than pure sequential version.

I have also inserted thread-yield statements so that all threads get chance to
run, but I see very little difference. Measured difference is probably due to
system fluctuation, rather than truly beacuse of thread scheduling (~0.1 sec on
a job of ~10 secs).

So, how to use threads in Emacs correctly? Is this me or is there just no
benefit of current thread implementation in Emacs? Sorry I don't mean to be rude
on thread implementation, but I am in doubt, should I just forgett about threads
or is there something I missunderstand about how to use them correctly?

The attached program is just about parsing files in emacs lisp dir for function
and macro defs (no frequency counting).


[-- Attachment #2: func-freq.el --]
[-- Type: text/plain, Size: 3579 bytes --]

;;; func-freq.el ---                                 -*- lexical-binding: t; -*-

;; Copyright (C) 2021  Arthur Miller

;; Author: Arthur Miller <arthur.miller@live.com>
;; Keywords: 

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; 

;;; Code:
(defun ff-print (map)
  (maphash (lambda (k v) (print (format "%s: %s" k v))) map))

(defun ff-collect-funcs-and-macros (src &optional keyword)
  (with-temp-buffer
    (insert-file-contents-literally src)
    (goto-char (point-min))
    (let (sxp features)
      (while (setq sxp (ignore-errors (read (current-buffer))))
        (when (and (listp sxp) (equal (car sxp) keyword))
          (push (cadr sxp) features)))
        features)))

(defun ff-freq-seq (dir-tree)
  (let ((fmap (make-hash-table :test 'equal))
        (mmap (make-hash-table :test 'equal))
        (srcs (directory-files-recursively dir-tree "\\.el$")))
    (dolist (src srcs)
      (dolist (f (ff-collect-funcs-and-macros src 'defun))
        (puthash f 0 fmap))
      (dolist (f (ff-collect-funcs-and-macros src 'defmacro))
        (puthash f 0 mmap)))))

(defun ff-freq-thr (dir-tree)
  (let (threads
        (fmap (make-hash-table :test 'equal))
        (mmap (make-hash-table :test 'equal))
        (srcs (directory-files-recursively dir-tree "\\.el$")))
    (dolist (src srcs)
      (push (make-thread #'(lambda () 
                             (dolist (f (ff-collect-funcs-and-macros src 'defun))
                               (puthash f 0 fmap)
                               ;;(thread-yield)
                               )
                             (dolist (f (ff-collect-funcs-and-macros src 'defmacro))
                               (puthash f 0 mmap)
                               ;;(thread-yield)
                               ))) threads))
    (dolist (thread threads)
      (thread-join thread))))

(defun ff-collect-macros (dir-tree map)
  (let ((srcs (directory-files-recursively dir-tree "\\.el$")))
    (dolist (src srcs)
      (dolist (f (ff-collect-funcs-and-macros src 'defmacro))
        (puthash f 0 map)
        ;;(thread-yield)
        ))))

(defun ff-collect-functions (dir-tree map)
  (let ((srcs (directory-files-recursively dir-tree "\\.el$")))
    (dolist (src srcs)
      (dolist (f (ff-collect-funcs-and-macros src 'defun))
        (puthash f 0 map)
        ;;(thread-yield)
        ))))

(defun ff-freq-thr2 (dir-tree)
  (let (fthr mthr
        (fmap (make-hash-table :test 'equal))
        (mmap (make-hash-table :test 'equal)))
    (setq mthr (make-thread #'(lambda () (ff-collect-macros dir-tree fmap))))
    (setq fthr (make-thread #'(lambda () (ff-collect-functions dir-tree mmap))))
    (thread-join mthr)
    (thread-join fthr)))

(benchmark-run 3 (ff-freq-seq (expand-file-name "~/repos/emacs/lisp")))
(benchmark-run 3 (ff-freq-thr (expand-file-name "~/repos/emacs/lisp")))
(benchmark-run 3 (ff-freq-thr2 (expand-file-name "~/repos/emacs/lisp")))

(provide 'func-freq)
;;; func-freq.el ends here

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

* Re: Experiment with threads - no concurrency?
  2021-09-06 14:35 Experiment with threads - no concurrency? Arthur Miller
@ 2021-09-06 15:17 ` Stefan Monnier
  2021-09-06 16:35   ` Arthur Miller
  2021-09-06 17:38   ` T.V Raman
  2021-09-06 15:47 ` Eli Zaretskii
  1 sibling, 2 replies; 10+ messages in thread
From: Stefan Monnier @ 2021-09-06 15:17 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

> Since it is kind of lot's of I/O and independent tasks to do, I thought threads
> could come handy. However I see no difference from sequential code.

This is a common misunderstanding, it seems.  To help us fix it, could
you tell us what parts of our docs (docstrings or Texinfo manual) you
consulted before coming here?


        Stefan




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

* Re: Experiment with threads - no concurrency?
  2021-09-06 14:35 Experiment with threads - no concurrency? Arthur Miller
  2021-09-06 15:17 ` Stefan Monnier
@ 2021-09-06 15:47 ` Eli Zaretskii
  2021-09-06 16:40   ` Arthur Miller
  1 sibling, 1 reply; 10+ messages in thread
From: Eli Zaretskii @ 2021-09-06 15:47 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

> From: Arthur Miller <arthur.miller@live.com>
> Date: Mon, 06 Sep 2021 16:35:04 +0200
> 
> I did a little experiment today. I wanted to count frequency of Emacs functions
> usage. So I started by indexing all functions and macros.
> 
> Since it is kind of lot's of I/O and independent tasks to do, I thought threads
> could come handy. However I see no difference from sequential code.

You shouldn't.  Emacs doesn't switch threads on just any I/O, it
switches threads when it waits for input from subprocesses, network,
and keyboard.



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

* Re: Experiment with threads - no concurrency?
  2021-09-06 15:17 ` Stefan Monnier
@ 2021-09-06 16:35   ` Arthur Miller
  2021-09-06 17:31     ` Eli Zaretskii
  2021-09-06 17:38   ` T.V Raman
  1 sibling, 1 reply; 10+ messages in thread
From: Arthur Miller @ 2021-09-06 16:35 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> Since it is kind of lot's of I/O and independent tasks to do, I thought threads
>> could come handy. However I see no difference from sequential code.
>
> This is a common misunderstanding, it seems. 
Well it woudl be probably misunderstanding on my part, since I thought that
threads are just a wrapper on pthreads and tried to translate my thread
understanding from other languages. As I am used to, I/O would normally block
and threads would be swtiched (in Java).

> you tell us what parts of our docs (docstrings or Texinfo manual) you
> consulted before coming here?
>

"Currently, thread switching will occur upon explicit request via thread-yield,
when waiting for keyboard input or for process output from asynchronous
processes (e.g., during accept-process-output), or during blocking operations
relating to threads, such as mutex locking or thread-join."

That is the only part that mentions where threads will switch, and it does not
mention blocking on I/O so I guess it was misunderstanding on my parts. Maybe it
can help guys like me, who assume things based on some previous usage from other
places and languages, if you mention this common misunderstanding somewhere, and
how Emacs threads compare to some other thread implementations like Java threads
or pthreads?

This also leaves me with a question: what is practical use for Emacs threads? Is
there any internal code that uses threads so I can look at a practical example?



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

* Re: Experiment with threads - no concurrency?
  2021-09-06 15:47 ` Eli Zaretskii
@ 2021-09-06 16:40   ` Arthur Miller
  2021-09-06 17:33     ` Eli Zaretskii
  0 siblings, 1 reply; 10+ messages in thread
From: Arthur Miller @ 2021-09-06 16:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Arthur Miller <arthur.miller@live.com>
>> Date: Mon, 06 Sep 2021 16:35:04 +0200
>> 
>> I did a little experiment today. I wanted to count frequency of Emacs functions
>> usage. So I started by indexing all functions and macros.
>> 
>> Since it is kind of lot's of I/O and independent tasks to do, I thought threads
>> could come handy. However I see no difference from sequential code.
>
> You shouldn't.  Emacs doesn't switch threads on just any I/O, it
> switches threads when it waits for input from subprocesses, network,
> and keyboard.

Allright, so in order to exploit I/O concurrency here, the only way is to  start
another emacs process asynchronously? Could split file list I get from
directory-files-recursively into say 4 parts, and process files in 4
processes. Is there any benefit to use threads in that case?

Not that it is terribly important, it takes like 3 seconds to parse all files in
lisp dir sequentially, but now when I opened the question ...



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

* Re: Experiment with threads - no concurrency?
  2021-09-06 16:35   ` Arthur Miller
@ 2021-09-06 17:31     ` Eli Zaretskii
  0 siblings, 0 replies; 10+ messages in thread
From: Eli Zaretskii @ 2021-09-06 17:31 UTC (permalink / raw)
  To: Arthur Miller; +Cc: monnier, emacs-devel

> From: Arthur Miller <arthur.miller@live.com>
> Date: Mon, 06 Sep 2021 18:35:16 +0200
> Cc: emacs-devel@gnu.org
> 
> Well it woudl be probably misunderstanding on my part, since I thought that
> threads are just a wrapper on pthreads

The are indeed wrappers of pthreads, but we don't use the pthreads
scheduler.

> This also leaves me with a question: what is practical use for Emacs threads? Is
> there any internal code that uses threads so I can look at a practical example?

You can start by looking at the tests for the thread capabilities.



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

* Re: Experiment with threads - no concurrency?
  2021-09-06 16:40   ` Arthur Miller
@ 2021-09-06 17:33     ` Eli Zaretskii
  2021-09-06 18:10       ` Arthur Miller
  0 siblings, 1 reply; 10+ messages in thread
From: Eli Zaretskii @ 2021-09-06 17:33 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

> From: Arthur Miller <arthur.miller@live.com>
> Cc: emacs-devel@gnu.org
> Date: Mon, 06 Sep 2021 18:40:46 +0200
> 
> > You shouldn't.  Emacs doesn't switch threads on just any I/O, it
> > switches threads when it waits for input from subprocesses, network,
> > and keyboard.
> 
> Allright, so in order to exploit I/O concurrency here, the only way is to  start
> another emacs process asynchronously?

Yes, I think so, because in this case the I/O happens inside Emacs
primitives.

> Could split file list I get from
> directory-files-recursively into say 4 parts, and process files in 4
> processes. Is there any benefit to use threads in that case?

No, I don't think so.

> it takes like 3 seconds to parse all files in lisp dir sequentially

You have tried that on relatively small directories, I think.



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

* Re: Experiment with threads - no concurrency?
  2021-09-06 15:17 ` Stefan Monnier
  2021-09-06 16:35   ` Arthur Miller
@ 2021-09-06 17:38   ` T.V Raman
  2021-09-06 18:11     ` Arthur Miller
  1 sibling, 1 reply; 10+ messages in thread
From: T.V Raman @ 2021-09-06 17:38 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Arthur Miller, emacs-devel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=gb18030, Size: 804 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:


Also, see a message I sent a  couple of weeks ago re threading, how
little it is used in emacs itself (from my quick check not at all).

It would be good to have a few exemplars of where emacs' thread support
actually helps to learn from and build out of going forward.
>> Since it is kind of lot's of I/O and independent tasks to do, I thought threads
>> could come handy. However I see no difference from sequential code.
>
> This is a common misunderstanding, it seems.  To help us fix it, could
> you tell us what parts of our docs (docstrings or Texinfo manual) you
> consulted before coming here?
>
>
>         Stefan
>
>

-- 

Thanks,

--Raman(I Search, I Find, I Misplace, I Research)
7©4 Id: kg:/m/0285kf1  •0Ü8



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

* Re: Experiment with threads - no concurrency?
  2021-09-06 17:33     ` Eli Zaretskii
@ 2021-09-06 18:10       ` Arthur Miller
  0 siblings, 0 replies; 10+ messages in thread
From: Arthur Miller @ 2021-09-06 18:10 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Arthur Miller <arthur.miller@live.com>
>> Cc: emacs-devel@gnu.org
>> Date: Mon, 06 Sep 2021 18:40:46 +0200
>> 
>> > You shouldn't.  Emacs doesn't switch threads on just any I/O, it
>> > switches threads when it waits for input from subprocesses, network,
>> > and keyboard.
>> 
>> Allright, so in order to exploit I/O concurrency here, the only way is to  start
>> another emacs process asynchronously?
>
> Yes, I think so, because in this case the I/O happens inside Emacs
> primitives.
>
>> Could split file list I get from
>> directory-files-recursively into say 4 parts, and process files in 4
>> processes. Is there any benefit to use threads in that case?
>
> No, I don't think so.
>
>> it takes like 3 seconds to parse all files in lisp dir sequentially
>
> You have tried that on relatively small directories, I think.

It was like all lisp that comes with Emacs :-) alis lisp dir in Emacs source
dir, I was looking for defuns and defmacros.

Anyway, thanks for the input, I'll look for the tests you mentioned in previous
mail, but it feels that I don't have much use of threads. Maybe if I had some
long running async process, I could check for results, but in this particular
case, I guess I have no use for threads.




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

* Re: Experiment with threads - no concurrency?
  2021-09-06 17:38   ` T.V Raman
@ 2021-09-06 18:11     ` Arthur Miller
  0 siblings, 0 replies; 10+ messages in thread
From: Arthur Miller @ 2021-09-06 18:11 UTC (permalink / raw)
  To: T.V Raman; +Cc: Stefan Monnier, emacs-devel

"T.V Raman" <raman@google.com> writes:

> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
>
> Also, see a message I sent a  couple of weeks ago re threading, how
> little it is used in emacs itself (from my quick check not at all).
Yes, I remember that message.

> It would be good to have a few exemplars of where emacs' thread support
> actually helps to learn from and build out of going forward.

I agree. 

>>> Since it is kind of lot's of I/O and independent tasks to do, I thought threads
>>> could come handy. However I see no difference from sequential code.
>>
>> This is a common misunderstanding, it seems.  To help us fix it, could
>> you tell us what parts of our docs (docstrings or Texinfo manual) you
>> consulted before coming here?
>>
>>
>>         Stefan
>>
>>



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

end of thread, other threads:[~2021-09-06 18:11 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-06 14:35 Experiment with threads - no concurrency? Arthur Miller
2021-09-06 15:17 ` Stefan Monnier
2021-09-06 16:35   ` Arthur Miller
2021-09-06 17:31     ` Eli Zaretskii
2021-09-06 17:38   ` T.V Raman
2021-09-06 18:11     ` Arthur Miller
2021-09-06 15:47 ` Eli Zaretskii
2021-09-06 16:40   ` Arthur Miller
2021-09-06 17:33     ` Eli Zaretskii
2021-09-06 18:10       ` Arthur Miller

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