Skip to content

Commit e78d643

Browse files
nikomatsakistmandry
andcommitted
metanarrative
Co-authored-by: Tyler Mandry <[email protected]>
1 parent 3fe5426 commit e78d643

File tree

1 file changed

+137
-3
lines changed

1 file changed

+137
-3
lines changed

src/vision/status_quo.md

Lines changed: 137 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,140 @@ These stories may not be true, but they are not fiction. They are based on real-
2828

2929
[roadmap]: ./roadmap.md
3030

31-
## Where are the stories?
32-
33-
Check the sidebar with the table of contents bar!
31+
## Metanarrative
32+
33+
*What follows is a kind of "metanarrative" of using async Rust that summarizes the challenges that are present today. At each point, we link to the various stories; you can read the full set in the table of contents on the left. We would like to extend this to also cover some of its glories, since reading the current stories is a litany of difficulties, but obviouly we see great promise in async Rust. Note that many stories here appear more than once.*
34+
35+
Rust strives to be a language that brings together performance, productivity, and correctness. Rust programs are designed to surface bugs early and to make common patterns both ergonomic and efficient, leading to a sense that "if it compiles, it generally works, and works efficiently". Async Rust aims to extend that same feeling to an async setting, in which a single process interweaves numerous tasks that execute concurrently. Sometimes this works beautifully. However, other times, the reality falls short of that goal.
36+
37+
<details><summary>Making hard choices from a complex ecosystem from the start</summary>
38+
39+
The problems begin from the very first moment a user starts to try out async Rust. The async Rust support in Rust itself is very basic, consisting only of the core Future mechanism. Everything else -- including the basic async runtimes themselves -- lives in user space. This means that users must make a number of choices rom the very beginning:
40+
41+
* what runtime to use
42+
* [Barbara makes their first foray into async](status_quo/barbara_makes_their_first_steps_into_async.md)
43+
* [Niklaus wants to share knowledge](status_quo/niklaus_wants_to_share_knowledge.md)
44+
* what http libraries to use
45+
* [Barbara anguishes over http](status_quo/barbara_anguishes_over_http.md)
46+
* basic helpers and utility crates are hard to find, and there are many choices, often with subtle differences between them
47+
* [Barbara needs async helpers](status_quo/barbara_needs_async_helpers.md)
48+
* Furthermore, the async ecosystem is fractured. Choosing one library may entail choosing a specific runtime. Sometimes you may wind up with multiple runtimes running at once.
49+
* [Alan started trusting the rust compiler but then async](status_quo/alan_started_trusting_the_rust_compiler_but_then_async.md)
50+
* [Barbara needs async helpers](status_quo/barbara_needs_async_helpers.md)
51+
* 🚧 Need a story about multiple runtimes working together
52+
* There is a lack of common, standardized abstractions, which means that often there are multiple attempts to establish common traits and different libraries will employ a distinct subset.
53+
* [`Sink` is not implemented by async-std websockets](status_quo/alan_tries_a_socket_sink.md)
54+
* 🚧 No standardized lower-level traits for read, write, iterators in an async setting
55+
* 🚧 Lack of widely used higher-level abstractions (like those tower aims to provide)
56+
* 🚧 Tokio doesn't support the futures `Stream` trait because of stability concerns
57+
* Some of the problems are due to the design of Rust itself. The coherence rules in particular.
58+
* 🚧 Write about how coherence makes it impossible to establish
59+
60+
</details>
61+
62+
<details><summary>Once your basic setup is done, the best design patterns are subtle and not always known.</summary>
63+
64+
Writing async programs turns out to have all kinds of subtle tradeoffs. Rust aims to be a language that gives its users control, but that also means that users wind up having to make a lot of choices, and we don't give them much guidance.
65+
66+
* If you need synchronization, you might want an async lock, but you might want a synchronous lock, it's hard to know.
67+
* [Alan thinks he needs async locks](status_quo/alan_thinks_he_needs_async_locks.md)
68+
* Mixing sync and async code is tricky and it's not always obvious how to do it -- something it's not even clear what is "sync" (how long does a loop have to run before you can consider it blocking?)
69+
* [Barbara bridges sync and async](status_quo/barbara_bridges_sync_and_async.md)
70+
* [Barbara compares some C++ code](status_quo/barbara_compares_some_cpp_code.md)
71+
* There are often many options for doing things like writing futures or other core concepts; which libraries or patterns are best?
72+
* [Barbara needs async helpers](status_quo/barbara_needs_async_helpers.md)
73+
* [Grace wants to integrate c api](status_quo/grace_wants_to_integrate_c_api.html#the-second-problem-doing-this-many-times)
74+
* [Barbara plays with async](status_quo/barbara_plays_with_async.md), where she tries a number of combinations before she lands on `Box::pin(async move { .. })`
75+
* If you would to have data or task parallel operations, it's not always obvious how to do that
76+
* [Barbara plays with async](status_quo/barbara_plays_with_async.md)
77+
* [Barbara tries async streams](status_quo/barbara_tries_async_streams.md)
78+
* [Niklaus builds a hydrodynamic simulator](status_quo/niklaus_simulates_hydrodynamics.md)
79+
* Sometimes it's hard to understand what will happen when the code runs
80+
* [Grace wants to integrate c api](status_quo/grace_wants_to_integrate_c_api.html#the-second-problem-doing-this-many-times)
81+
* [Barbara bridges sync and async](status_quo/barbara_bridges_sync_and_async.md)
82+
* Sometimes async may not even be the right solution
83+
* [Niklaus builds a hydrodynamic simulator](status_quo/niklaus_simulates_hydrodynamics.md)
84+
85+
</details>
86+
87+
<details><summary>Even once you've chosen a pattern, gettings things to compile can be a challenge.</summary>
88+
89+
* Async fn doesn't work everywhere
90+
* [not in traits](status_quo/alan_needs_async_in_traits.md)
91+
* not in closures -- [barbara plays with async](status_quo/barbara_plays_with_async.md)
92+
* [barbara needs async helpers](status_quo/barbara_needs_async_helpers.md)
93+
* Recursion doesn't work
94+
* [barbara needs async helpers](status_quo/barbara_needs_async_helpers.md)
95+
* Things have to be Send all the time, some things can't live across an await
96+
* [send isn't what it means anymore](https://tomaka.medium.com/a-look-back-at-asynchronous-rust-d54d63934a1c)
97+
* [alan thinks he needs async locks](status_quo/alan_thinks_he_needs_async_locks.md)
98+
* The tricks you know from Sync rust apply but don't quite work
99+
* e.g., Box::pin, not Box::new -- [barbara plays with async](status_quo/barbara_plays_with_async.md)
100+
* Sometimes you have to add `boxed`
101+
* [Grace tries new libraries](status_quo/grace_tries_new_libraries.md)
102+
* Writing strings is hard
103+
* [Grace wants to integrate a C API](status_quo/grace_wants_to_integrate_c_api.html#the-second-problem-doing-this-many-times)
104+
* When you stray from the happy path, the complexity cliff is very steep
105+
* Working with Pin is really hard, but necessary in various scenarios
106+
* 🚧 Need a story about implementing async-read, async-write
107+
* [Alan hates writing a stream](status_quo/alan_hates_writing_a_stream.md)
108+
* It's easy to forget to invoke a waker
109+
* [Alan hates writing a stream](status_quo/alan_hates_writing_a_stream.html#-frequently-asked-questions)
110+
* [Grace deploys her service](status_quo/grace_deploys_her_service.md)
111+
* Ownership and borrowing rules get really complicated when async is involved
112+
* [Alan writes a web framework](status_quo/alan_writes_a_web_framework.md)
113+
* Sometimes you want `&mut` access that ends while the future is suspended
114+
* [Alan lost the world](status_quo/alan_lost_the_world.md)
115+
* [Ghostcell](status_quo/barbara_wants_to_use_ghostcell.md)
116+
* Writing executors is pretty non-trivial, things have to have references to one another in a way that is not very rusty
117+
* [barbara builds an async executor](status_quo/barbara_builds_an_async_executor.md)
118+
119+
</details>
120+
121+
<details><summary>Once you get it to compile, things don't "just work" at runtime, or they may be unexpectedly slow.</summary>
122+
123+
* Libraries are tied to particular runtimes and those runtimes can panic when combined, or require special setup
124+
* [Alan started trusting the rust compiler but then async](status_quo/alan_started_trusting_the_rust_compiler_but_then_async.md)
125+
* [Alan picks a web server](status_quo/alan_picks_web_server.md)
126+
* Cancellation can in principle occur at any point in time, which leads to subtle bugs
127+
* [Alan builds a cache](status_quo/alan_builds_a_cache.md)
128+
* [Alan finds dropping database handles is hard](status_quo/alan_finds_database_drops_hard.md)
129+
* [Barbara gets burned by select](https://github.com/rust-lang/wg-async-foundations/pull/169)
130+
* Dropping is synchronous but sometimes wants to do asynchronous things and block for them to complete
131+
* [Alan finds dropping database handles is hard](status_quo/alan_finds_database_drops_hard.md)
132+
* Nested awaits mean that outer awaits cannot make progress
133+
* [Footgun with futures unordered](https://github.com/rust-lang/wg-async-foundations/issues/131)
134+
* Async functions let you build up large futures that execute without allocation, which is great, but can be its own cost
135+
* [Alan iteratively regresses](status_quo/alan_iteratively_regresses.md)
136+
* [Alan runs into stack allocation trouble](status_quo/alan_runs_into_stack_trouble.md)
137+
* It's easy to have async functions that inadvertently spend too long in between awaits
138+
* [Barbara compares some C++ code](status_quo/barbara_compares_some_cpp_code.md)
139+
140+
</details>
141+
142+
<details><summary>When you have those problems, you can't readily debug them or get visibility into what is going on.</summary>
143+
144+
* The state of the executor can be very opaque: what tasks exist? why are they blocked?
145+
* [Alan tries to debug a hang](status_quo/alan_tries_to_debug_a_hang.md)
146+
* [Barbara wants async insights](status_quo/barbara_wants_async_insights.md)
147+
* [Grace deploys her service](status_quo/grace_deploys_her_service.md)
148+
* Stacktraces are full of gobbly gook and hard to read.
149+
* [Barbara trims a stacktrace](status_quo/barbara_trims_a_stacktrace.md)
150+
* Tooling doesn't work as well with async or just plain doesn't exist.
151+
* [Grace waits for gdb](status_quo/grace_waits_for_gdb_next.md)
152+
* [Alan iteratively regresses](status_quo/alan_iteratively_regresses.md)
153+
154+
</details>
155+
156+
<details><summary>Rust has always aimed to interoperate well with other languages and to fit itself into every niche, but that's harder with async.</summary>
157+
158+
* Runtimes like tokio and async-std are not designed to "share ownership" of the event loop with foreign runtimes
159+
* [Alan has an event loop](status_quo/alan_has_an_event_loop.md)
160+
* Embedded environments can have pretty stringent requirements; Future was designed to be minimal, but perhaps not minimal enough
161+
* [Barbara carefully discusses embedded future](status_quo/barbara_carefully_dismisses_embedded_future.md)
162+
* Evolving specs for C and C++ require careful thought to integrate with async Rust's polling model
163+
* 🚧 Convert [these notes on C++](https://hackmd.io/DnArulWbTKSx1_8mijsRuQ) into a status quo story
164+
* 🚧 Write about the challenges of io-uring integration
165+
* Advanced new techniques like [Ghostcell](status_quo/barbara_wants_to_use_ghostcell.md) may not fit into the traits as designed
166+
167+
</details>

0 commit comments

Comments
 (0)