Writing Network Drivers in Rust [pdf]
net.in.tum.de
net.in.tum.de
This is a rough approximation of a quote he gave during the talk:
"What makes Rust different is not that you can write high-performance, bare-metal code. People use C and C++ to do that all the time. What makes Rust different is that when you write that code, it is safe, clean, and easy to use, and you are confident in its correctness."
If even Google is using Rust for performance-critical development, that seems pretty promising to me.
[1]: https://www.youtube.com/channel/UCptxtVyJkQAJZcFwBbIDZcg
Ideally, under a capability-based OS, you can just have a unikernel that directly loads user-supplied(!) modules in a bytecode format where instructions have capability-checking as an intrinsic; and then, after performing static analysis on those modules to guarantee that they don’t do anything crazy, the kernel module loader can JIT them into native code that doesn’t need to do the capability checks. Basically like if the entire userland consisted of ePBF programs—but with higher-level exposed semantics that allow for rich access to kernel structures, rather than just their handles.
Plus, you also get the benefit of safe sharing of higher-level data abstractions. A “native” userland process has to make syscalls using, at most, registers containing pointers to strings or fixed-size non-polymorphic structs. A capability-based userland module, meanwhile, could interact with the kernel even through reads and writes to a shared-memory tree or hashmap.
Essentially, with capabilities, you get all the benefits of every program having the same low-overhead access to the kernel that a kernel driver does, with none of the drawbacks of having to guard against corrupting the kernel’s state.
https://fuchsia.googlesource.com/garnet/+/master/go/src/nets...
https://github.com/fuchsia-mirror?language=go
I'm pretty sure Go is the dominant language for networking in Fuchsia and not Rust.
(Only partly a joke.)
Too bad the odds are 10000:1 that I get stuck doing Java/Go instead.
Fuschia/Rust is about the only thing I'd do at Google.
There's also the story of the Google+ UI lead who though he'd be working on another Google product, then got reassigned before he was even hired into G+ and hated his entire 9mo having never even met with Vic the VP driving G+.
Does that still happen?
"In kernel space there is an API to allocate DMA memory, in user space we have to use other mechanisms since this API is not available here. To disable swapping, we can use mlock(2). [...] However, mlock(2) only ensures that the page is kept in memory. The kernel is still able to move pages to different physical addresses. To circumvent this problem, we use huge pages with a size of 2 MiB. These pages cannot be migrated yet by the Linux kernel, thus stay resident in physical memory."
He didn't, he's depending on an implementation quirk which might change in the future (and also depending on the physical memory backing huge pages being in a region which can be reached by the network device through DMA, though that's probably always true on x86 when memory encryption is not in use).
I’m extremely bullish on Rust, it’s such a breath of fresh air to be able to write maintainable, modern code to do low level tasks. I was a C/C++ dev for a little under a decade before switching to Rust and it really delivers on its promises.
Also Rust using llvm is a huge boon to writing eBPF programs.
"Based on our findings we can conclude that Rust is a very well-suited programming language for writing network drivers. It is not only a fast and safe systems programming language but was also voted most beloved programming language in 2016, 2017 and 2018 [15, 16, 17]. Writing more drivers in Rust would certainly lead to safer and more reliable computer systems."
Working link to their code: https://github.com/ixy-languages/ixy.rs
It's the second order effects that matter.
For instance these past few days I've been writing a small bootloader for some embedded ARM chip. I pondered going with Rust but ended up using C for two main reasons:
- I know that if it's doable in Rust it's doable in C but the opposite is not always true (or straightforward). In particular bare-metal/very low level Rust is still somewhat experimental, you can't use stable Rust if you want to be able to use inline ASM or other advanced features. I have very tight constraints regarding code size and memory use and I was concerned that I might not control that as effectively with Rust code than with C.
- There's already a bunch of C code written for this chip that I can reuse without any friction (no binding generation, no ffi etc...). The vendor even provides a huge header file with the full memory map and some code to init the PLLs.
If you're coding in a vacuum then how "beloved" a language is is mostly irrelevant but if you want to benefit from the ecosystem then having a language that people want to use and support is extremely important. The tooling will mature and stabilize as more and more people use Rust to write bare-metal code and device drivers, which will eventually make my first point above irrelevant. Then if the language becomes popular enough it will be easier to find Rust code or pre-made crates to do what you want which will hopefully eventually solve my 2nd issue.
Since I can't get u-boot to create a small enough image with all the features that I want (and also because I want to add vendor-specific customizations on top) I decided to try and rewrite a small, single purpose loader from scratch. I considered Rust but then that meant that I'd have to port or rewrite all of u-boot's code I want to reuse (especially the vendor code contributed by Altera mentioned in the previous post). So C it is.
Still, I do think you're right that a significant number of people hate C++, so I think your point is still valid.
Heck, in some industries, like aviation, even something subjective like boredom can kill.
> An OS kernel — despite its historic appeal and superficial fit for Rust — may represent more challenge than its worth
However it suggests more hybrid approaches:
* asm/C kernel with Rust kernel components like drivers and filesystems, Rust can be used for new developments and enable an incremental introduction, mentions a prototype example in freebsd
* Rust for non-kernel OS components: an OS is not just a kernel and utilities, daemons, management facilities, debuggers, … bundled as part of the system tend to be more prone to run-time failures than the kernel itself (and more commonly face hostile interactions), making them excellent candidates for Rust
* Rust-based firmwares: firmware is "a sewer of unobservable software with a long history of infamous quality problems", some areas of firmware (and kernel) development are weak in rust (e.g. dealing with allocation failure) but that aside it looks amenable to Rust
Also, it really comes down to whether or not it's a long-term win. Apple certainly has the capital to make it happen if they decided it was worth it.
The bachelor project was more of the same, but each group should do a part of a bigger piece of software. I don't recall having any academic references in our final report.
It was a very nice way to learn, as you had your group members to study with and learn from each other.
This was in Denmark, Aalborg University. Which have just been named the best engineering university in Europe, and the fourth best in the world [0].
[0] https://www.usnews.com/education/best-global-universities/en...
Here's another report from MIT from earlier this year, reporting largely the same, placing Aalborg at 3rd or 4th depending on the method used [0].
[0] http://neet.mit.edu/wp-content/uploads/2018/03/MIT_NEET_Glob...
(I graduated from the Mechanical Engineering Faculty of the TUM.)
A large part of my thesis was implementing a language server for the DOT/Graphviz language [0]. It really depends on the professor.
However, the only thing that matters for the mark is the thesis itself. Many students spend too much time implementing their project and have not enough time for the thesis itself.
[0]: https://edotor.net
https://news.ycombinator.com/item?id=18399389
I'm excited to read both of these.
Seeing that this is an undergrad thesis makes me feel like I did nothing in undergrad. I'm impressed
That would make the ports still be an interesting experiment, but not as impressive IMO.
Some things hard in one language are easy in another, and it usually helps to have a good understanding of both. Just my own POV. However, low level code often requires one to do things "the hard way" for performance reasons. I particularly appreciate what Go, Rust, C# and others bring to the table.
Most of the code I write isn't particularly performance intensive, so I tend to reach for JS in early implementations. Though happy to rewrite if/when performance becomes a concern. I really enjoy articles like this.
Good to remember that C and Unix kernels haven't always had a monopoly on device drivers.
Unsafe usage is quite small, at 10%, which seems good for a hardware device driver.
That doesn't apply to driver development, but it might be surprising to someone only moderately familiar with the language.
C++ implementations obey the zero-overhead principle: What you don’t use, you don’t pay for [Stroustrup, 1994]. And further: What you do use, you couldn’t hand code any better. – Stroustrup
It's close to insignificant to comparing two languages. Especially when they boil down to things like:
let ptr = unsafe {
libc::mmap(
ptr::null_mut(),
len,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
file.as_raw_fd(),
0,
) as *mut u8
};
vs calling something like this in one line in C, etc.The C version also crams every line together, the Rust version couples related statements but leave newlines between others (not sure if loc counts those too).
Of course, correctness trumps almost everything in programming. Rust seems like a really nicely balanced programming language that can replace C++ and C and provide additional protection against some kinds of common errors made by programmers. So it’s definitely on my list of languages to try next for a project.
Even so, 1300 vs 1000, or 1.3x is not really in the "so much more as to be more difficult to read" category.
In fact it can be in the "better worded and easier to read category" (e.g. a monolithic stream of code without functions and comments vs one with).
Rust might end up being just right, not too concise, like Haskell or APL, and not too verbose, like Java or Ada; it could be a Goldilocks language.
Rust can go low-level, but its succintness (compared to C) is when dealing with high-level structures. Things like vectors, hashmaps, or even strings. Those rarely are use on a driver.
In addition to that: in C you can share a pointer in many places and write memory wherever you want. Since rust has ownership system things get a little more complicated. Sometimes you have to write extra code to appease the borrow checker.
Consider that you will never get the situations you get in C, where forgetting to check for NULL in one place can result in privilege escalations (example: https://www.exploit-db.com/exploits/33322/). I think it's worth it.
At least it's linked here: https://www.in.tum.de/fuer-studierende/bachelor-studiengaeng...
While Rust is nice in some areas, I'm not convinced this is anything more than yet another "let's rewrite it in Rust, because I happen to like Rust" article.
Angry comments defending Rust incoming in 3..2..
Rust version will not be safer if the authors did 10 times more errors per line than average C programmer.
[0] https://en.wikipedia.org/wiki/Substructural_type_system
These types of comments really irritate me. New thing X comes out that solves an unsolved problem. Then someone comments "why not obsolete thing Y that doesn't solve the problem sufficiently"?
I constantly see comparisons like JVM vs WASM [1], or in this case Ada vs Rust. And very often the newer thing is superior and is not popular just because of cargo culting.
[1] i.e. To obtain similar performance while still using java bytecode you will have to stop using the Java object model completely and exclusively use sun.misc.Unsafe and calculate field offsets of structs manually and still have the risk of vulnerabilities like buffer overflows similar to writing programs in C.
No it isn't. The GC has to touch that data, which means it's cache pressure, which means it's perf pressure.
> And, once again, GC is optional.
Sure, but it's an exclusive choice between memory safety and speed. Other languages let you have your cake and eat it too in that respect (Cyclone, Rust, etc.).
* The Rust borrow checker prevents a lot of issues in C(++) code. Including thread safety. Nim does not provide anything new in this regard.
* The lack of a GC is a feature, not a detriment. One of the reasons why Rust applications are often very fast is because the language naturally guides you to avoid allocations when possible and allows low level control where necessary. Combined with the safety guarantees of the borrow checker, this is a powerful combination. This is possible in Nim but using GC is easier and will be the preferred solution when in doubt.
* While Mozilla support does help a lot for sure, a lot of the hype around Rust (imo) comes from people trying it out, just falling in love with and then promoting it
If there was no rampant tribalism, my comment would not be buried with negative votes. It would receive a response like the one you gave, which is subjective, and that would be the end of it. Some may even up-vote it because diversity is always good. But feels like Rust users are zealous and it's a bad sign, tbh. Wouldn't want to be part of a community that acted with hostility towards others for presenting alternative view points.
Rather, your comment seemed rather "tribal" while criticizing Rust fans of the same.
BTW, I would see Nim more as a competitor to D, Swift and Java than to Rust.
It has several tunable GCs allowing for great flexibility there, and also supports running with no GC at all. It compiles to C that will compile nearly anywhere C does. It produces smaller binaries, and it can easily link against musl instead of libc for an even lighter footprint. It's also safe like Rust is, and the compiler will help you catch a ton of errors.
That's not to say that it's competitive at this point in time. It's much more unstable as a language due to not reaching 1.0 yet. They only just (August) received any real kind of funding, allowing them to hire on a new developer but it's still just a handful of core devs and some dedicated contributors. The standard library and the community repo (Nimble) can't compare with Rust's and Cargo in terms of package availability and support.
I'm not sure if you were implying that it doesn't, but Rust also supports musl:
$> rustup target list | rg musl
aarch64-unknown-linux-musl
arm-unknown-linux-musleabi
arm-unknown-linux-musleabihf
armv5te-unknown-linux-musleabi
armv7-unknown-linux-musleabihf
i586-unknown-linux-musl
i686-unknown-linux-musl
mips-unknown-linux-musl
mipsel-unknown-linux-musl
powerpc64le-unknown-linux-musl
x86_64-unknown-linux-muslThere's a fair bit of overlap for obvious reasons: they're two languages suited for the same tasks, after all :)
You can paint others opinion as being subjective, which they are, but you would be wise to realize yours are as well. That's what's bringing hostility, not the diversity of viewpoint (there's a lot of talks about Go in the thread for example)
Actually Nim does offer something new in this regard. See https://nim-lang.org/docs/manual.html#guards-and-locks.
> While Mozilla support does help a lot for sure, a lot of the hype around Rust (imo) comes from people trying it out, just falling in love with and then promoting it
AFAIK Rust was a much different language before Mozilla officially adopted it (wasn't the borrow checker implemented after Mozilla sponsorship?). So not only was it not the same language, it wasn't known at all. Don't underestimate the power of full-time developers working on a programming language and having the support of a well known organisation behind them.
Sadly a lot of the hype is simply "omg, Mozilla uses this langauge" or "omg, Google uses this language".
Just take a look at the basic problem of multi-threading: two threads write to the same memory location. This situation is unpredictable and there never allowed to happen. There are three general strategies to deal with this: immutability, mutexes and linear types to ensure there is only one reference with write capability.
The latter makes writing code that is not thread-safe impossible at compile time without sacrificing efficiency and is used by at least two programming languages that I know of: Ponylang and Rust. For me impossible vs "oops forgot to guard it" are worlds apart. The compiler will inform you that it is not thread-safe and then you can decide to use a different solution like a mutex if necessary.
> Tests show that a 2ms max pause time will be met in almost all cases on modern CPUs (with the cycle collector disabled).
So in a reduced mode, pause times are only bounded by 2ms. Not sure how you could say that is zero pause
Some embedded realtime cases might have more strict deadline requirements, or be complicated by the potential jitter that a GC might intoduce. Eg most discrete math used in motor control systems assumes a fixed sample period.
Rust is possibly an ideal language for game development. Standard Rust has no runtime component, which is perfect. It's also a high-performance language.
The ecosystem for Rust game development is immature, but there's progress being made.
https://www.reddit.com/r/rust/comments/9twam5/jemalloc_was_j...
Trying to promote Nim like you are doing might in fact have the opposite effect :/
My statement is based on my opinion. There are certainly imperfections in Nim even bugs and things that annoy me but the mental load is far less than working in Rust, for me that is, and so to me it is better in every way since in the end I find it to be congruent with my mental model whereas I can’t say the same about Rust. It is a purely opinionated statement like everything else where meaning is involved. We are the meaning makers. It doesn’t exist in detached form.
Your opinion is valid.