[ruby-core:91528] Re: Technical question on ruby Thread::Light scheduling

From: Eric Wong <normalperson@...>
Date: 2019-02-13 09:44:52 UTC
List: ruby-core #91528
Responding to technical bits from a private email I got
regarding this topic: (original asker Bcc-ed).

Note: I'm focused on another project nowadays, so I have almost
no time or interest in Ruby.  Maybe 2020 will be different.
Non-technical questions to be answered privately.

> You mention in
> https://80x24.org/ruby.git/commit/?h=thread-light&id=2d5766886fc6b8575daaa79d4549c944b464eab4
> :
> 
> Thread::Light scheduling happens at a few, well-defined points
> +     *        only when the execution context cannot proceed (e.g. waiting
> on
> +     *        a message from a socket, pipe, Queue, or similar).
> 
> - Given the fact that Ruby Threads are rescheduled when they block on IO,
> does the above mean you have some fine-grained scheduling mechanism that
> switches auto-fibers in-between Thread switching?

Yes.  Except auto-fibers can only switch when socket/pipe I/O
cannot proceed.  FS I/O blocking is not easily/portably detectable.

> - Regading Mutexes, if you make them 'just' auto-fiber aware then you
> should get Thread-awareness for free, right?

No.  I've already forgotten the exact details (but maybe my old
emails/docs describe it); but I seem to recall doing deadlock
checking right is difficult.  So preventing auto-fiber switching
inside a mutex lock seemed to be the most logical way towards
predictable/safe behavior (similar to Thread.exclusive in 1.8).

> - you mention you need native threads yourself to support FS access with
> high-throughput/low latencies. Is this because ruby 'provides' time-slicing
> sheduling ?

No, not at all.  It's because the ONLY way to get any sort of
parallelism for most FS syscalls is to use native threads.
POSIX AIO only offers functionality of read/write/fsync.

Stuff like open/stat/unlink/link/rename/readdir/pread/pwrite
requires native threads (or processes) for parallelism.

> - In golang they have an integrated netpoller, which I wager is in line
> with your idea of a single IO events 'distributor'. It relies on epoll for
> linux, kqueu for bsd, iocp for windows etc.
> Just mentioning in case you want to look for some inspiration:
> https://golang.org/src/runtime/netpoll.go (OS-generic),
> https://golang.org/src/runtime/netpoll_epoll.go,
> https://golang.org/src/runtime/netpoll_kqueue.go.

Maybe... but no mention of EV_ONESHOT or EPOLLONESHOT; so it
looks like they'll get extra/unneeded wakeups and
netpollready/netpollunblock needs to filter out duplicate
events.

> - Regarding fiber/coroutine/auto-fiber migration between ruby Threads,
> golang has solved the problem in an elegant way: goroutine stack lives in
> program heap with malloc, switching goroutines need only to save and
> restore 3 registers: Program Counter, Stack Pointer and DX. Ruby seems to
> be a bit stuck into "moving stacks between threads" mentality, when the
> ligher abstractions should be oblivious to underlying OS threads. This
> allows you to schedule the next goroutine/auto-fiber in the runq into
> another unblocked thread and run it right away. Care to share some thoughts?

Ruby could do this if we dropped support for C-extensions, too.

But the current VM itself is like one giant C-extension, and
critical parts which benefit from auto-fiber scheduling
("socket"), are, too; as are popular gems which would benefit from
this feature, such as "pg" or "mysql2"

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread

Prev Next