Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use rb_io_wait function and cache io instance. #47

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ioquatix
Copy link

Copy link
Contributor

@matthewd matthewd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for following up on this @ioquatix!

{
struct trilogy_ctx *ctx = ptr;

if (RTEST(ctx->io))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mark moveable doesn't check if the field is NULL, IIRC without this it can crash.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was looking at https://github.com/ruby/ruby/blob/1fdaa0666086529b3aae2d509a2e71c4247c3a12/gc.c#L7108 and https://github.com/ruby/ruby/blob/1fdaa0666086529b3aae2d509a2e71c4247c3a12/gc.c#L10395 -- I'm not 100% sure it's part of their defined contract, but I imagine it must be true by ossification, even if not originally intended?

Intuitively I just prefer "this slot contains a a possible GC ref", rather than an [even trivial] encoding of "we might need to mark this". 🤷🏻‍♂️

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's possibly not the greatest interface.

contrib/ruby/ext/trilogy-ruby/cext.c Show resolved Hide resolved

return 0;
VALUE result = rb_io_wait(ctx->io, RB_INT2NUM(wait_flag), rb_fiber_scheduler_make_timeout(timeout));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I acknowledge it's what's already happening on sufficiently-new rubies (along with the IO construction), but rb_fiber_scheduler_make_timeout sounds like it might allocate. Is that true? Something we can/should avoid?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a small chance I the future it might allocate but for the moment it doesn't, it just embeds a float into the VALUE. I hope at some point in the future to migrate to fixed point timeouts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bonus question: is this going to affect our min ruby version (which I note we don't seem to currently declare)? I'm guessing this is moderately recent.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I'll add feature detection, this PR is just what I could manage in the 30 minutes I had before bed time.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it just embeds a float into the VALUE

Flonums only work for a subset of all double, if it doesn't fit it will be an allocation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it also always allocate on 32bits?

@ioquatix
Copy link
Author

ioquatix commented Feb 25, 2023

@matthewd can you please approve and run the workflows.

@ioquatix ioquatix force-pushed the main branch 3 times, most recently from 61269c1 to dc88886 Compare February 25, 2023 07:47
@ioquatix
Copy link
Author

There is one more piece we should consider exposing, which is the "resolve DNS" to use the fiber scheduler hook.

@ioquatix
Copy link
Author

So, writing this PR has made me realise we need a set of shims for the blocking C APIs, e.g. open, addrinfo, etc. We have the code, it's just not exposed. I supposed we can do that for Ruby 3.3.

We should also extend the test suite to run within a fiber scheduler (probably Async).

@matthewd
Copy link
Contributor

matthewd commented Mar 2, 2023

@ioquatix is this good to go? It seems fine to me, not sure if you've kept it in draft for a reason, or just not hit the button?

@ioquatix
Copy link
Author

ioquatix commented Mar 2, 2023

It's probably as good as we can make it.. but I want to review it this weekend. This week has been pretty busy, have not had much time for open source stuff.


#ifdef TRILOGY_RB_IO_WAIT
if (ctx->io == Qnil) {
ctx->io = rb_io_fdopen(fd, O_RDWR, NULL);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trilogy_data_type is marked with RUBY_TYPED_WB_PROTECTED, so you have to trigger a write barrier here.

Problem is you don't have access to the VALUE here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so we should pass around the VALUE then?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either that, or create the IO eagerly in a place where you have access to it.

@kirs
Copy link

kirs commented Oct 4, 2024

👋 just wanted to say that I appreciate this WIP PR by Samuel and I'd really really love to see this happen in the upstream, and to be able to use trilogy with fiber scheduler for IO-heavy workloads.

@casperisfine
Copy link
Contributor

I'd really really love to see this happen in the upstream, and to be able to use trilogy with fiber scheduler for IO-heavy workloads.

So my knowledge of the fiber scheduler is limited, but AFAIK you can already use it today? My understanding is that this PR make it a bit more efficient, but rb_wait_for_single_fd is already enough to be usable.

As for it happening, there's not much work needed, all the blockers are listed in review comments.

@ioquatix ioquatix marked this pull request as ready for review October 25, 2024 05:24
@ioquatix
Copy link
Author

I've rebased and updated the PR.

rb_wait_for_single_fd is okay but it's a slow path. rb_io_wait is the fast path.

@matthewd can you please run CI.

@ioquatix ioquatix force-pushed the main branch 3 times, most recently from cc37ef9 to a3baae0 Compare October 25, 2024 06:47
contrib/ruby/ext/trilogy-ruby/cext.c Outdated Show resolved Hide resolved
contrib/ruby/ext/trilogy-ruby/cext.c Outdated Show resolved Hide resolved
contrib/ruby/ext/trilogy-ruby/cext.c Outdated Show resolved Hide resolved
@ioquatix ioquatix force-pushed the main branch 5 times, most recently from 55e6591 to ab563aa Compare October 25, 2024 07:56
@ioquatix
Copy link
Author

ioquatix commented Oct 25, 2024

I recall why I gave up on this PR for a while, we were missing rb_io_open_descriptor which is needed to create a "temporary non-owning FMODE_EXTERNAL IO instance". Since that's now available in recent CRuby, it is possible to implement it correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants