ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: SASADA Koichi <ko1@atdot.net>
To: Ruby developers <ruby-core@ruby-lang.org>
Subject: [ruby-core:81028] Re: [ruby-cvs:65407] normal:r58236 (trunk): thread.c: comments on M:N threading [ci skip]
Date: Mon, 8 May 2017 10:53:05 +0900	[thread overview]
Message-ID: <38090d10-c6a1-5097-66af-130275d773ea@atdot.net> (raw)
In-Reply-To: <20170508003315.GA3789@starla>

On 2017/05/08 9:33, Eric Wong wrote:
> I have been thinking about this again; think M:N green Thread is
> a bad idea[1].  Instead we should improve Fibers to make them
> easier-to-use for cases where non-blocking I/O is _desirable_
> (not just _possible_).

Great. That is exactly we are thinking. To discussion, let's define such
auto-scheduling fibers "auto-fiber"

> * not enabled by default for compatibility, maybe have:
>   Fiber.current.auto_schedule = (true|false) # per-fiber
>   Fiber.auto_schedule = (true|false) # process-wide
>   But I do not do Ruby API design :P

Yes. I'm thinking to introduce new constructor like ScheduledFiber.new
or something like that (maybe that name is not suitable, too). I believe
we shouldn't change the behavior just after creation.

BTW, we need to define the behavior of Fiber#resume, Fiber.yield and
Fiber#transfer for auto-fibers.

* Permit to use them.

> * Existing native-thread code for blocking IO must (MUST!)
>   continue blocking w/o GVL as in current 2.4.
>   Users relying on blocking accept4() (via BasicSocket#accept)
>   still gets thundering herd protection when sharing listen
>   socket across multiple processes.
>   Ditto with UNIXSocket#recv_io when sharing a receiver socket.

Not sure about this. We need to define I/O blocking operation again for
this auto-switching fiber (maybe the following your documents define them).

> * documented scheduling points:
> 
>   TL;DR: most existing "blocking" APIs become Fiber-aware,
>   similar to 1.8 green threads.
> 
>   - IO operations on pipe and sockets inside Fibers with
>     auto-scheduling enabled automatically become Fiber-aware
>     and use non-blocking internal interfaces while presenting
>     a synchronous API:

Only pipe and sockets?

>         IO#read/write/syswrite/sysread/readpartial/gets etc..
>         IO.copy_stream, IO.select
>         Socket#connect/accept/sysaccept
>         UNIXSocket#recv_io/#send_io
>         IO#wait_*able (in io/wait ext)
> 
>   - Ditto for some non-IO things:
> 
>         Kernel#sleep
>         Process.wait/waitpid/waitpid2 family uses WNOHANG
>         Queue/SizedQueue support, maybe new Fiber::Queue and
>         Fiber::SizedQueue classes needed?

Just now, Fiber::Queue is not good idea I think because it is difficult
to switch Thread::Queue and Fiber::Queue. However, I agree that we need
to introduce scheduling primitives and Queue is good to use. We need to
introduce it carefully.

>   - keep Mutex and ConditionVariable as-is for native Thread
>     user, I don't believe they are necessary for pure Fiber use.
>     Maybe add an option for Mutex locks to prevent Fiber.yield
>     and disable auto-scheduling temporarily?

I can't understand that. Mutex (and so on) are for Threads. Does they
need to care Fibers?

>   - IO#open, read-write I/O on filesystem release GVL as usual

Not sure why they do.

>   - It will be necessary to use resolv and resolv/replace in
>     stdlib for Fiber-aware name resolution.

It seems difficult...

> * Implementation (steps can be done gradually):
> 
>   1. new internal IO scheduler using kqueue/epoll/select.  Native
>      kqueue/epoll allow cross-native-thread operation to share
>      the event loop, so they only need one new FD per-process.
>      I want to avoid libev/libevent since (last I checked) they
>      do not allow sharing an event loop across native threads.
>      I can write kqueue/epoll/select parts; I guess win32 can use
>      select until someone else implements something
> 
>      Maybe build IO scheduler into current timer thread....

I planned to run per-thread Fiber scheduler and to use epoll (and so on)
on the thread because of overhead of cross-thread communication. I think
we need to compare them (I didn't try it yet).

>   2. pipes and sockets get O_NONBLOCK flag set automatically
>      when created inside Fibers with auto-scheduling set.

not sure about it.

>   3. rb_wait_single_fd can use new IO scheduler and becomes
>      Fiber-aware, ditto with rb_thread_fd_select...
> 
>      Steps 2 and 3 should make most IO changes transparent.
> 
>   4. make necessary changes to Process.wait*, IO.select,
>      Kernel.sleep
> 
> 
> 
> Side note: I consider making Fibers migratable across native
> Threads out-of-scope for this.  We currently use
> makecontext/swapcontext (FIBER_USE_NATIVE) for speed (which
> according to cont.c comments is significant).  I am not
> sure if we can keep FIBER_USE_NATIVE if allowing Fibers
> to migrate across native threads.
> 
> 
> [1] general problem with threads:
>     timeslice scheduling leads to unpredictability
>     like Mutex/ConditionVariables become necessary.
> 
>     M:N will be problematic, as it will be difficult for
>     users to know when it is safe to use heavy native threads
>     for blocking operations and when their threads will be
>     lightweight; making it difficult to design apps to use
>     each appropriately.
> 
>     However, native 1:1 Threads will always be useful for cases
>     where users can take advantage of blocking I/O
>     (#recv_io/#accept/File.open/...) as well as releasing GVL
>     for CPU-intensive operations independent of Ruby VM.
> 
> Thanks for reading, I wrote most of this while waiting for
> tests to r58604 to run before committing.
> 
> Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>
> 


-- 
// SASADA Koichi at atdot dot net

  reply	other threads:[~2017-05-08  1:09 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20170402011414.AEA9B64CEE@svn.ruby-lang.org>
     [not found] ` <8a2b82e3-dc07-1945-55f9-5a474e89130b@ruby-lang.org>
2017-04-02  2:35   ` [ruby-core:80531] Re: [ruby-cvs:65407] normal:r58236 (trunk): thread.c: comments on M:N threading [ci skip] Eric Wong
2017-04-02  3:05     ` [ruby-core:80532] " SASADA Koichi
2017-04-03  4:42       ` [ruby-core:80540] " Eric Wong
2017-05-08  0:33         ` [ruby-core:81027] " Eric Wong
2017-05-08  1:53           ` SASADA Koichi [this message]
2017-05-08  2:16             ` [ruby-core:81029] " SASADA Koichi
2017-05-08  3:01               ` [ruby-core:81031] " Eric Wong
2017-05-08  3:42                 ` [ruby-core:81033] " SASADA Koichi
2017-05-08  6:36                   ` [ruby-core:81035] " Eric Wong
2017-05-09  2:18                     ` [ruby-core:81042] " SASADA Koichi
2017-05-09  3:38                       ` [ruby-core:81044] " Eric Wong
2017-05-09  4:11                         ` [ruby-core:81045] " SASADA Koichi
2017-05-09  5:12                           ` [ruby-core:81047] " Eric Wong
2017-05-09  5:47                             ` [ruby-core:81049] " SASADA Koichi
2017-05-09  6:23                               ` [ruby-core:81053] " Eric Wong
2017-05-09  6:44                                 ` [ruby-core:81054] " SASADA Koichi
2017-05-09 18:51                                   ` [ruby-core:81078] " Eric Wong
2017-05-10  3:24                                     ` [ruby-core:81083] " SASADA Koichi
2017-05-10 10:04                                       ` [ruby-core:81089] " Eric Wong
2017-05-19  4:34                                         ` [ruby-core:81244] " Eric Wong
2017-06-20 19:16                                   ` [ruby-core:81733] " Eric Wong
2017-05-09  5:54                             ` [ruby-core:81050] " SASADA Koichi
2017-05-09  6:15                               ` [ruby-core:81052] " Eric Wong
2017-05-08  2:56             ` [ruby-core:81030] " Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=38090d10-c6a1-5097-66af-130275d773ea@atdot.net \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).