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

A yield_now/yield_local alternative that allows the thread to go to sleep #1135

Open
james7132 opened this issue Feb 25, 2024 · 3 comments
Open

Comments

@james7132
Copy link

james7132 commented Feb 25, 2024

We're investigating using rayon as Bevy's thread pool and scheduler, and part of that requires being able to schedule futures onto the task pool. This has been partially doable with the suggested implementations in the discussion in #679, but we're running into issues where futures::block_on equivalents cannot yield to the thread pool in a way that will put the thread to sleep if there is no available work, nor a way to, on-demand, wake that specificthread back up. futures_lite::block_on and it's variants park the thread using parking or the std equivalent in std::thread::park, but rayon does not expose any option for this level of control. Using the aforementioned options for parking the thread leads to excessive CPU usage and contention, likely due to conflicting with rayon's internal state of how threads should be managed.

A yield_sleep or yield_park equivalent that hooks into the internal thread sleeping state when called, and a corresponding data type that we can wrap as a Waker would be really useful here.

@cuviper
Copy link
Member

cuviper commented Feb 26, 2024

Can you sketch what this might look like from the outside?

@james7132
Copy link
Author

james7132 commented Feb 26, 2024

pub struct Parker;
pub struct Unparker;

impl Parker {
    /// Either does one job, or does an additional round of polling via Sleep, eventually putting the thread to sleep, blocking the
    /// thread until woken up by rayon or the provided Waker.
    pub fn yield_or_sleep(&self) -> Yield {}
}

// The converted Wakes up the paired thread.
impl From<Unparker> for std::task::Waker {
    ...
}

/// Linked to WorkerThread::current
pub fn pair() -> (Parker, Unparker) {}

If this is too much to expose to a public interface, it's probably fine to also just have this internally inside rayon_core to make a potential rayon_core::futures::block_on as an equivalent to futures_lite::futue::block_on.

@cuviper
Copy link
Member

cuviper commented Feb 27, 2024

it's probably fine [...] to make a potential rayon_core::futures::block_on

Oh! I had a prototype of that -- here it is dusted off and rebased:
main...cuviper:rayon:block_on

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

No branches or pull requests

2 participants