Repository navigation
Replies: 2 comments 7 replies
|
Thanks for the detailed RFC and for having a working prototype already — that makes this much easier to discuss concretely. I'd strongly suggest using Tokio (Rust) as the primary reference design when working through the open questions below. Tokio is the most battle-tested async runtime in a systems language, and V's constraints (fast compilation, simplicity, no GC-heavy design) are close enough to Rust's that many of Tokio's lessons transfer directly. Concrete points where Tokio's experience is worth borrowing:
· Future trait: poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll — a pull model. Your prototype's Future[T] as a "shared handle + await blocks until ready" is closer to a push/blocking model. Consider adopting the poll-based contract internally even if the surface syntax stays await expr — it makes the waker mechanism (your roadmap step 5) natural rather than bolted on.
· Reactor (I/O driver, epoll/kqueue/io_uring), Keeping these as separate vlib modules (even if the syntax is unified) will make it far easier to test each in isolation and to swap backends (e.g. add io_uring later as -d use_io_uring). This also aligns with your question 4 — I'd vote for io_uring as a separate reactor backend behind a flag, not baked into net.
· Future cancellation (dropping a future cancels it), or
Summary of concrete recommendations: · Stackless state machines (Tokio model), not stackful fibers. Happy to help review the state-machine transform design when you get to roadmap step 4 — that's where the Tokio comparison will matter most. |
|
Thanks for the RFC. The Given that, have you considered extending Was this alternative considered? If so, what were the arguments against it? |
Uh oh!
There was an error while loading. Please reload this page.
Summary
I'm proposing native
async/awaitsupport in V, and I already have aworking (synchronous) prototype. The goal is to let V programs handle
100K+ concurrent I/O-bound tasks (HTTP servers, database queries, file
processing) with a small number of threads, instead of being capped at
the number of OS threads.
This is a discussion first. I want to align with maintainers before
investing months in the state-machine transform.
Why this matters for V (not just for one use case)
V is already fast and simple, which makes it attractive for servers,
tools, and infrastructure. But today, concurrency in V is
spawn/go,i.e. one OS thread per task. That caps real-world concurrency at the
number of cores (typically 4–16) and adds context-switch overhead. For
I/O-bound programs — which are most server programs — this is the main
bottleneck, not CPU.
Other languages V competes with (Go, Rust, Zig, JS) all have cooperative
coroutines. V already has the building blocks (channels,
spawn, fastcompilation). Adding
async/awaitwould let V compete in theserver/infrastructure space without giving up simplicity.
Concrete V programs that would benefit:
veb/ HTTP servers: 10K+ concurrent connections on a few threads.db.sqlite/db.pg/db.mysql: non-blocking queries, connectionpools without thread-per-request.
What I'm proposing
async fn foo() TreturnsFuture[T].await exprsuspends the coroutine without blocking the thread.spawn async fn()launches a coroutine on the scheduler.Prototype status
A first, conservative prototype already exists (in my fork of v, on the
feature/async-awaitbranch):async fn/await exprparse and type-check.async fnreturnsFuture[T]; body is wrapped so callers get a Future.Future[T]is a shared handle, soawaitobserves completion frombackground work.
spawn_async(f)andsleep_async(ms)run work on background threads.awaitblocks until the Future is ready.The prototype keeps synchronous semantics first, so it's safe to review
and adjust without risk.
Performance goal
The bar is: equal or better than today's synchronous/threaded model,
not worse. Concretely:
the heap, GC-friendly).
must be measured and kept in check.
vself_speed.mdmethodology (paired runs,instructions retired, fixed fixture).
Roadmap (incremental, PR-sized)
Future[T]type (done in prototype).Future[T](done).vlib/v/transform(the big one) — splitinto many small PRs, each with tests.
net(epoll/kqueue, then io_uring).Each step will be a small PR with tests, not one monolithic change.
Open questions for maintainers
async/awaitas language keywords, or do youprefer keeping async at the library level (
vlib/x/async)?incremental syntax PRs acceptable?
more compiler work) vs stackful (fibers, simpler, more memory)?
-d/flag) or integrated intonetbehind a flag?compilation fast", "don't touch thirdparty")?
What I'm asking for
Future[T],await,spawn).I'm happy to adapt the design to whatever the maintainers prefer. The
prototype is intentionally conservative (synchronous semantics first) so
it can be reviewed and adjusted without risk.
Thanks!
All reactions