← Back to context

Comment by gpm

3 days ago

You already do, to the kernel. It's probably not much more costly to do so an extra time in userspace.

I yield to the kernel to allow other threads that do some kind of background work to run. Do I want my application's async tasks to yield every 10ms? I assume that is what is being meant here.

  • That is a valid concern! To clarify:

    Configurability: We absolutely plan to make the 10ms yield interval configurable (or opt-out) in the runtime settings. It is currently a default safety rail to prevent async starvation, not a hard constraint.

    Concurrency Options: It is important to note that LOGOS has three distinct execution primitives, and this yield logic doesn't apply to all of them:

    Simultaneously: (Parallel CPU): This compiles to rayon::join or dedicated std::threads. It does not use the cooperative yield check, allowing full blocking CPU usage on separate cores.

    Attempt all: (Async Join) & Launch a task: (Green Threads): These compile to tokio async tasks. The cooperative yield is specifically here to prevent a single heavy async task from blocking the shared reactor loop.

    So if you need raw, uninterrupted CPU cycles, you would use Simultaneously, and you wouldn't be forced to yield.

  • with cooperative scheduling, yes. This is indeed something missing from the Rust async ecosystem, tasks are meant to be IO-bound and if they become CPU-bound accidentally they will starve other tasks (async-std tried to fix this, but had some backlash due to overhead IIRC). Go actually puts a yield on every loop body (or used to), to prevent starvation. A 10ms thing will have negligible impact

    Also: yielding to the kernel is very costly. Yielding to another task in your own thread is practically free in comparison