samuel / oriontransfer.org wrote:
> It would be also be pretty awesome if you could actually
> supply a reactor to use, e.g. `Fiber.new(io_reactor:
> my_reactor)`. In this case, blocking operations would call
> `my_reactor.wait_readable(io)` and
> `my_reactor.wait_writable(io)`. Something like this allows for
> the IO policy to be more flexible than global per-process
> reactor or other similar implementation. I'm still personally
> against a global IO reactor as it's an unnecessary point of
> thread contention and complexity (i.e. how does it work with
> fork? does every IO operation require locking a mutex?)

Global epoll FD is not anywhere close to being a point of thread
contention in real-world usage, especially with current GVL.

If epoll contention ever comes close to being a problem, I'll
fix it in the Linux kernel.  I worked on reducing that
contention in the kernel a few years back but couldn't measure
an improvement outside of synthetic benchmarks with the workload
I had at the time (which wasn't ruby and had no GVL).

Of course unbuffered IO operations will not require mutexes and
fork is taken into consideration.  For example, it accounts for
native kqueue having unique close-on-fork behavior which no
other FD type has.

Btw, your use the word "reactor" is a bit lost on me.
My view of epoll (and kqueue) is the sum of two data structures:

  a. map structure (rbtree, hash, etc...)

  b. readiness queue (why else does "kqueue" have the word "queue" in it)?

And what happens is:

  1. green thread gets stuck on IO

  2. native thread epoll_ctl/kevent(changelist) to places items into a.

  3. kernel puts items in a. into b. when they are ready

  4. threads take items off b. via epoll_wait/kevent(eventlist)

I don't think "reactor" describes that, because reactor pattern
is rooted in a single thread mentality.  epoll/kqueue invite
parallelism.

Now, I'm hungry, maybe it's the "restaurant kitchen pattern",
and the analogy would be:

  1. patrons order food from a waiter

  2. waiters puts in orders into the kitchen

  3. cooks work on orders, prepared plates are placed on the counter

  4. waiters takes plates from counter and serves to patrons

There can be any number of waiters and cooks working, and in no
way are their quantities tied together.

Each waiter can handle multiple patrons, but sequentially.
Waiters may also put in orders for themselves.

Some plates take a long time to prepare, some plates are quick;
some plates are ready immediately.
Many orders may come in at once, or they can trickle in.
Many plates can be ready at once, or they can trickle out.

cooks = native threads inside the kernel
waiters = native threads seen by userspace
patrons = green threads

As with green threads and the kernel, cooks never see
the patrons and don't know how many there are.

Waiters don't care or know which cook prepares the plate they
serve.  Cooks don't care which waiter the plate goes to, either.

> So, as mentioned earlier, `libpq` and the associated `pq` gems
> won't suddenly become asynchronous because of this patch
> (seems like there is a bit of a misunderstanding how this
> works under the hood). In fact, we can already achieve massive
> concurrency improvements using `async`, and I've tested this
> using `puma` and `falcon`. The difference was pretty big! I
> wrote up a summary here:
> https://github.com/socketry/async-postgres#performance

Of course things don't become asynchronous automatically.
Again, I've seen this all before with Revactor, NeverBlock, etc.
Problem is, if it's not in built-in, it'll likely end up
unused or causing more ecosystem fragmentation.  Lets not forget
many languages ruby has lost users to (Go, Erlang) has similar
lightweight threading primitives built-in.

And again, I consider this work to be fixing a regression when
we made the 1.8 -> 1.9 transition to native Thread.

> feel free to come and chat in https://gitter.im/socketry/async
> as there are a quite a few people there who are interested in
> the direction of asynchronous IO in Ruby.

Sorry, it's not reasonable to expect Free Software developers to
rely on proprietary messaging platform like GitHub (which gitter
depends on).

> So, again, I think this patch is simply does too much. It
> should be split into 1/ a standard IO reactor for Ruby with a
> standard interface that others can implement (could easily be
> a gem) 

Maybe exposing some parts of the mapping + queue API might
be possible.  Again, I don't think "reactor" is even the right
pattern or word to describe what's going on, here.

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