--- title: "Rust use cases" tags: ["T-lang", "design-meeting", "minutes"] date: 2024-09-09 url: https://hackmd.io/lsWQnwGCT1qP8pvBDka8gA --- # Meetup 2024: Rust Use Cases Abstract: Let's talk about the most important use cases for Rust, now and in the future, and highlight some unique needs of each. Preparation: Please add to the sections below. Artifact: A list of important, emerging, and notable use cases. Include what we know and what we don't know about the support each of the important and emerging ones needs. Examples: Web services, CLI tools, Kernels and hypervisors, Embedded. ## Introduction Rust's values of reliability, security, and productivity are sorely needed in our industry. But there are many obstacles to Rust adoption in specific areas. Understanding these areas and the obstacles they face can help us streamline Rust adoption and open the floodgates for more investment in Rust. ## High-level Outline ### Firmly established Use cases where multiple major companies or projects are using Rust as one of their primary languages for new development. Despite being "firmly established", Rust, being a relatively new language, still has lots of room to grow. - Web servers, microservices - Microservice infrastructure - Operating systems services (desktop and mobile) - CLI tools - WebAssembly - Cryptography ### Gaining traction Areas where Rust has started to gain traction, but isn't quite firmly established yet. - Drivers - Kernels and Hypervisors - Embedded - Parsers ### Notable Exciting areas where experimentation has begun, but the value proposition of Rust is not well established yet. - High-reliability systems - Graphics - GUI apps - Scientific computing - AI ## Deep Dives Here we will dive into some specific use cases and talk about their unique needs (met and unmet). In addition to verticals, feel free to include specific projects and companies here, but keep the focus on their most important unique needs. ### Kernels and Hypervisors * Fallible allocation * Capability-shaped reasoning: * Allocation * Taking/Holding a lock * `#[no_panic]` * Controlling stack use * Overflow analysis * Using heap / intrusive linked lists for destruction * Intrusive data structures * Disable access to FPU ### Embedded * Similar to kernels and hypervisors * Highly memory constrained * Binary size * Stack * Heap * Highly storage constrained (binary size) ### Linux kernel * Wants to support building with distro-furnished rustc. ### Google monorepo * Extremely large C++ codebase * No clean place to make a language cut; deep two-way interop is needed * All built from source ### Report on Amazon's experience Current Amazon users are at-scale dataplanes (drawn in by Rust's tail latency) and consumer and embedded devices (drawn in by memory usage) and low-level systems software like Firecracker (relying on low-level capabilities). Most users start with Rust because of some particular need but wind up appreciating the "if it compiles, it works" feeling as well as the tooling. The typical Amazon service builder is not especially familiar with low-level details. Many of them have worked exclusively in Java and high-level languages. One (very capable) programmer I spoke with told me that they attempted to learn Rust twice. The first time, they bounced off. "It took me months to understand what a variable was in Rust", they said. They have now learned it and feel productive. It is difficult to judge the "learning curve". Many teams are very succesful with no challenges at all. Others report that some people just have a hard time. "I have people come in to standup for weeks telling me they're still working on the same thing. That never used to happen with Java", is a paraphrased (from memory) quote from one manager. **Service teams.** The typical Amazon service application runs on Linux and is fairly "high-level". Allocation is pretty common. Trait objects are used to isolate aspects of the service from one another and to enable unit testing. At the language level, challenges that come up frequently are (a) async language features, of course, and complex interactions around deadlocks etc (see e.g. this status quo story); (b) better support for dependency injection and unit testing; and \(c) a sense that there's a "lot to learn" (e.g., macros, etc). **Library vendors.** A lot of teams vend libraries internally within Amazon. These libraries are often written in Java but we are attempting to advocate for Rust, as it will allow them to support more languages. Teams are interested but concerned about the challenges having programmers working both in Java (on the main service) and in Rust. Learning curve details become very important in this environment. Architecturally these libraries are "roughly the same" as the code one sees in service team environments (high-level, heavy use of traits, etc). **Redpen and ability to 'steer and guide' teams at scale.** One thing I am very excited about is customized linting and diagnostics. ## GUI and mobile Rapid iteration is important. Want to make a change and quickly see the result. Ideally, want to have live reloading. Data structures and lifetimes tend to be hard. Lots of Arc as a result. Want Arc to be easier. For mobile, hard to integrate with build systems and requirements for putting apps together. ## Discussion ### Amazon TC: There are some situations where you have to have had the problem to understand the solution. Git is like this. Rust is similar. I've you've never worked in a large codebase you can look at Rust and say "what's all this stuff for". Niko: Also need to address person who is generally working in Java and needs to drop down, may be a little skeptical of Rust, etc. Scott: At some point it doesn't matter that much if it's static or dynamic typed if you have GC, OO, and reflection. TC: What about greenfield stuff? Niko: Depends on the domain. Probably if you're writing something new, data plane at high scale, it's going to be Rust. Control plane stuff generally harder, you have to call into Java. Robotics is same, but coming from C++. Niko: Want to pull out representative stories where Rust is kind of lacking. Scott: Feel like maybe if we were balancing different requirements (allocation fine or deep embedded stuff) we would make a different language Niko: Not so much that allocation is fine, it's that I want a starting point where we aren't leaving huge amounts on the table like Java. It's stuff like as_ref. > Niko: L6 who doesn't know what a pointer is TC: Does our story on stability and lack of runtime play into this, in terms of avoiding the problems that come up when trying to upgrade a JDK or Python version? Niko/Felix: It's more the lack of predictability. Josh: I used to work on something called real-time Java that was intended to solve this. Today you would just write it in something other than Java. TC: If your engineers wrote code where they cloned everything it would be fine, then you could just profile it? Niko: Nice story, but not quite true. Profiling is not that easy. Clone can be distributed throughout a codebase. Scott: Sometimes I try separating out clones and to_owned. The cases I want to separate are "I have an owned copy and need a second one" vs "I have a reference and now I need an owned copy". DTolnay had an interesting post about this a while ago <https://users.rust-lang.org/t/to-string-vs-to-owned-for-string-literals/1441/6?u=scottmcm> /me niko sketches * Use-cases and personas * High-level engineer helping drive Rust adoption to get * Mid-level engineer onboarding to Rust from (GC'd language) * C/C++ developer needing to reuse C++ libraries that use "all the things" * Questions * GUI etc? ### Linux kernel deep-dive * Rust is a guest and C is in charge. This may change but there's always this risk -- whenever Rust needs a change, will this be the time people get sick of it? * RfL is place where a lot of the "minor annoyances" become much more highlighted * small bits of friction can be a real turn-off, anything to deal with papercuts is welcome * esp from the perspective of "I know how to do this in C...why won't the language let me" * "you can write (Fortran|C) in any language" -- hit challenges doing it the "C way" and going deep in wrong direction * Niko: Amazon version is "how do I mock a struct" (so I can write unit tests) * RfL is trying to build out high-level, safe abstractions, so you can do stuff without having to deal with full details * Two-tiered: People who care and are fluent enough to write the abstractions, and People who are just going to power their way through. TC: Kernel C programmers jumping in and writing bad Rust code is what success looks like. Josh: Big wins would be - Can we make it so you don't need to write so many layers of abstraction to use Rust - Can we make it so you don't have to mess with cbindgen, just `#use std::vec::Vec` - Better gcc backend? Felix: One thing that stands out to me is having to write parallel definitions for data structures in multiple language and hope that tests catch if things don't match anymore. Josh/Felix: Ideal is to have one definition used from multiple places; a very good intermediate step would be to test that two things match statically. TC: The fact that we are built on LLVM gives us an opportunity to use Clang. Personas * Rust abstraction consumers * what they want? rust-ified versions of all interfaces they'll need * Rust abstraction producers * what they want? capabilities like derive(smart pointer) * Kernel C developers who don't want to care about Rust * what they want? stability If you do this right... * "Linux Rust makes Linux C better and Linux C makes Linux Rust better" ? * Rust helping clarify interfaces * C helping Rust stretch its capabilities Josh: Al Viro's patch set is a great example of this. ### GUI (copied from notes below) pnkfelix: I also wanted to double-check: Graphics and GUI are listed under Notable, but its not totally clear to me whether Rust actually has the right value-proposition in those spaces, either today or for the long term. So much of that space is dependent on integration with other tools (e.g. for building one's GUI via some kind of Interface Builder or similar), and I don't know of existing frameworks that are meant to integrate with Rust there. So I imagine it tends to be more of "do it via code", which may appeal to some but I'm not sure if it scales to the workforces today nor expected for the long-term. (This is reflected in my opening note that maybe the relevant gaps are not in the language, but rather in libraries+tooling...) joshtriplett: Two main cases of use-cases * Native UIs -- in this case, Rust has less to offer, could help distribute common code, core logic; would like better interop with various toolkits, though, and people *do* want this. * Cross-platform UIs -- a la React Native etc * Rust can be a good option here * Lots of work trying to make this work - iced, dioxus, ... Niko: Big counterpoint to this stuff is the web. * pnkfelix: so what is the takeaway from that insight? That we shoudl double-down on WASM? * niko: not necessarily, consider react-native. *(wait: we don't know how that works...)* TC: Raph Levien (raphlinus) has done a lot of work on investigating what the right UI code patterns are in Rust. See, e.g.: - https://www.xilem.dev/ - https://xi.zulipchat.com/ - https://linebender.org/blog/xilem-2024/ - https://github.com/linebender/xilem Someone is writing a tiling Wayland compositor in Rust: - https://github.com/YaLTeR/niri Scott: Makes me think of games (and how bevy worked around limitations of Rust) - If more people would write their netcode in Rust, even if their physics code is still C++, it'd be a big win Josh: Iteration speed is a big one for game dev and GUI. Incremental compile and link. Live reloading. Want to get as close as possible to "tweak code and immediately see GUI change", or vice versa (drag around bits of GUI and see the code change). TC: Evolution of use cases from e.g. react to svelte is moving to a more statically driven narrative. This reframing fits well with Rust. Same angle that Raph is taking. Ties in also with ergonomic ref counting initiative. Cases I've seen where people struggle are the ergonomics of closures and cloning of UI objects. Solving this at the language level could make a big difference. nikomatsakis: I don't think the use cases are as in conflict as you might think. The things people ask for here... * what are the "asks" from "GUI" programmers? * So far mostly they overlap with things other programmers want: * ergonomic ref-counting * labeled parameters (SDK -- another potential use case) * compilation speed + live reloading etc * I forget the typical list off top of asks. Probably coherence rules. :) ...are pretty aligned with what others need. So if things are aligned, seems like a good thing to try and support. ### Use cases notes (pnkfelix) pnkfelix: Preface to all of the comments below: its possible that some use cases don't care about language concerns, and their true source of impedence is more about (1.) library or (2.) tooling issues. So while I wrote a lot below, I'm actually not sure its necessarily worth that much discussion amongst our team... Having said that... pnkfelix: Not sure if this is already covered by the existing lists, but based on the head-hunter emails I receive, it seems like Rust is getting attention in the blockchain + finance space, for some reason. (Do we want to trust the "job market" as a metric for anything here?) pnkfelix: I also wanted to double-check: Graphics and GUI are listed under Notable, but its not totally clear to me whether Rust actually has the right value-proposition in those spaces, either today or for the long term. So much of that space is dependent on integration with other tools (e.g. for building one's GUI via some kind of Interface Builder or similar), and I don't know of existing frameworks that are meant to integrate with Rust there. So I imagine it tends to be more of "do it via code", which may appeal to some but I'm not sure if it scales to the workforces today nor expected for the long-term. (This is reflected in my opening note that maybe the relevant gaps are not in the language, but rather in libraries+tooling...) pnkfelix: Finally, a space where I *would* expect Rust to be successful is in places where real-time constraints are paramount; e.g. hardware with real-time interactive needs. (I'm thinking AR/XR specifically here.) Yet I'm not aware of Rust having much impact there (e.g is there Oculus Quest support? Vision Pro support -- I know of a T-compiler MCP for supporting VisionOS as a target, that's the extent of that...). So: *should* Rust be having an impact here? ### Fallible allocation thought (This might be better deferred to "vibe checks") Josh: People regularly suggest having an operator for `unwrap`. We've usually been resistant to that, because you should use better error handling. But we do have lots of functions that panic internally. Imagine if we had postfix `!` for unwrap (or something similar). Would we then have made more functions return an error rather than panicking, because it's trivial to add `!` if you just want to panic? This seems like a way in which language design and library design are closely intertwined. libs-api is hesitant to add `try_*` variants of *every single function that allocates*. We'd like a better solution, possibly with some language help. Is there a language design philosophy that could help us here? nikomatsakis: I'm in favor of `!` as an unwrap method ### On audiences and use cases nikomatsakis: My feeling from Amazon is that use cases are *almost* secondary. There are specific blockers around the things people are doing, but by far the biggest obstacle is perception (and reality) around learning curve and the ability to "scale up". Running a company at large scale means having programmers of all levels of experience, but mostly low experience (interns, undergrads, new hires) and so ability to "ramp up" on Rust is really important. ### Driving down the static/dynamic distinction pnkfelix: One high-level point, right now things like our rules re object-safe methods and handling of associated items implies that you have to decide upfront whether a given trait is designed to be used as a dyn Trait or not. And this seems bad; I would much prefer a world where you didn't have to think so hard as a library designer about whether the trait you're designing is meant to be used as a dyn trait or not. What language changes can we make to make it easier for people to just write traits and have them support dyn out of the box? pnkfelix: (I raise this because I think a lot of initial prototypes focus on the static trait use-case, and then after you get N thousand lines in, your customers realize for various reasons that they would have been much better off if they could have used dyn trait in more cases...) NM: I have a bit of thoughts here Felix, mostly in terms of making it possible to use "subsets of a trait" (e.g., `&dyn Foo`) would let you invoke `Foo` NM: suggestion: lets do this as an Unconf topic instead ### People trying to write "FORTRAN/C in any language" end up in weird places Josh: There's a common expression that "you can write FORTRAN in any language" or "you can write C in any language". Rust makes that fairly hard, though. And when people try hard (rather than trying to learn native Rustic approaches), they end up in *weird* places in Rust that make us go "how did you get here?!". (Relatedly: "what are you trying to do".) TC: "A bunch of C programmers jumping in and writing 'bad' Rust code is what success looks like." ### People interoperating between Rust and C Should be able to do this automatically. Include C headers/source from Rust. Include Rust modules from C. Felix: Could we make it easier to *check* that C and Rust data structures match, without having to jump through hoops? Josh: Agreed; most -sys crates *don't*, because it's not trivial to do so. That'd be a good intermediate step. TC: We're built on LLVM; it sometimes seems we should take more advantage of it.