Hypothetically, if I was writing an open source library for game development or HFT (two other big users of C++ code), would the Rust community respond similarly to use of unsafe code? In HFT at least we have zero concern for buffer overflow vulnerabilities and the like because we're not on the open internet, rather we're running in a colo directly connected to the exchange, so we face no risk from security vulnerabilities in code (as long as the code works as intended). I imagine it's similar for games, where unless you're writing DRM it doesn't matter if somebody gets root on their own gaming device (and even if your code is perfectly secure, they can still try to modify the code in memory to exploit it).
In which case the "downside" from unsafe code is much less (it's not going to leak an entire database of people's private details to the web), so would people still make such a big fuss about removing it? Especially if removing it involves any performance compromise, which in HFT at least would be unacceptable (or at least politically unacceptable when trying to sell Rust).
What's the particular benefit Rust offers you in such a scenario? Part of the appeal of Rust is memory safety, per-compile correctness, and enforcing best practices.
If you wrote a game engine in Rust, and open-sourced it, you'd probably get similar grief. Because that's what Rust is largely about. Anyways, certain high performance render applications (browsers, ahem), don't seem to suffer significant penalties.
Also, I'd argue that memory safety/rce protection/etc is crucial in games, particularly ones that are online. HFT running in a contained env? Less so, for sure.
>What's the particular benefit Rust offers you in such a scenario? Part of the appeal of Rust is memory safety, per-compile correctness, and enforcing best practices.
It's a modern language: no #includes, faster compilation (compared to template-heavy C++), nice macros, compile-time reflection (libraries like Serde are really nice), generally nicer stdlib than C++, decent package manager. And it's one of the only languages with RAII/destructors, which to me are one of the best things about C++.
>Also, I'd argue that memory safety/rce protection/etc is crucial in games, particularly ones that are online.
This applies to the server, but not to the graphical game client running on the user's machine, as the client is usually not accepting random inbound connections, instead it just connects to the server.
>This applies to the server, but not to the graphical game client running on the user's machine, as the client is usually not accepting random inbound connections, instead it just connects to the server.
There have been a few demonstrated RCEs in game clients (especially in P2P models which many modern games use).
Rust has a large value proposition even if you don't care much about safety. It compiles to fast, portable binaries, it has a good library ecosystem that's easy to leverage with cargo, and it has lots of nice language features (algebraic data types, traits, RAII, etc.). There's not a lot else that offers that feature set, so diverse kinds of programmers are inevitably going to drawn to it.
I like Rust because it makes it harder for yourself to shoot yourself in the face with something. Isolating problems is a charm in Rust code.
However from experience I can say that you can use Rust against the grain, which will result e.g. in constant fights with the borrowchecker, weird solutions to get around the typesystem and a ton of unsafe (=trustme) blocks.
Rust can do a lot for you, you just have to think a little more about a programs architecture and don't force paradigms like OOP onto it.
Safety has to deal with soundness, which can be related to security. They are not synonyms.
Whatever you're doing, you should care about soundness. In games and HFT unsound code leads to segfaults or undefined behavior, not necessarily security issues.
I suppose the difference is it's much easier to get code "sound enough" through unit testing and asan/Valgrind when you know you'll never have to deal with deliberately crafted adversarial input. Whereas in a server or web browser "sound enough" is not good enough, because given enough time somebody will probably find a way to exploit any unsoundness, so the only option is to be completely sound.
The advantage of rust is that you can write it soundly the first time, without a barrage of unit tests and manual (and slow!) runs through asan/valgrind memcheck.
There are a handful of places where safety guarantees can (in some cases) actually cause performance issues. Most common would be iterators created from nested adapters over slices of known length. But that's the kind of thing unsafe exists for and no one is going to get fussy about you using the escape hatch for the manual checks.
But most of the soundness guarantees of rust can't be avoided without a bit of effort even within unsafe blocks, and don't come with performance hits. That is because the core promise of borrow checker is that it guarantees you will not create multiple mutable aliases of the same data through your program logic (you can only really do this with manual pointer hackery, edit: or interior mutability primitives).
That's what omits things like iterator invalidation and use after move/free from being composable in the language itself, and they're things that asan and valgrind can't really catch unless you're fuzzing the crap out of your program during testing. But that's a lot of effort and developer time sitting around to make a best guess about something not happening that doesn't have performance impacts.
But really at the end of the day, soundness, memory safety, secure, these are correlated but different concepts that most programs have to deal with in one way or another.
Just a point of clarification that I found helpful - the patches offered to correct soundness problems, in this case, didn’t significantly impact performance. Your hypothetical still stands, but it’s not necessarily a huge trade off.
What about Actix's use of unsafe code in general? In most of the TechEmpower benchmarks Actix seemed to dominate, beating not only the other Rust frameworks but even C++. This is not because of a correlation between the use of unsafe and increased performance?
Not really, no. Most of Actix's unsafe code was unnecessary, and had largely been replaced with equivalently performant safe code over a long series of unpleasantly adversarial patches leading up to the final debacle. Much of the ire directed at the maintainer grew out of an impression that the maintainer was using unsafe to cut corners instead of finding alternative safe solutions. I believe that at the time of project's deletion it had only low 10's of remaining uses of unsafe.
That's quite unfortunate then, the ecosystem losing its fastest web server because of its use of unsafe when the use of unsafe wasn't even necessary for performance.
Well, “the community” is not as a whole happy about the outcome or the way this issue was handled in any way shape or form. I think Steve did a really good job of articulating the undercurrent behind this.
People should be allowed to be free of harassment. I think everyone would have been better off in this case if the individuals who were so concerned about the unnecessary safety, forked Actix and had a SafeActix, that was maintained without the usage they were concerned about.
If the maintainer isn’t going to accept your patches, then it’s time to decide how to move forward without needing to resort to harassment.
Games these days are frequently multiplayer, so the assumption they don't care about security is not necessarily supported. Something like fortnite would probably be a juicy target. Or maybe league, since even though it probably has less people, they're probably a more affluent population (w/the assumption that they're older)
I code with Rust for roughly two years and I must say I never once needed a unsafe block. If people are using unsafe blocks over and over, they are either working on the lowest layer of abstraction or they are still stuck in different ptogramming languages and didn't know about the wonderful solutions Rust has to offer if you let it.
I always like to translate unsafe in my head to "trust me I checked this very thoroughly" — if there are indicators that the author doesn't deserve that trust, I just won't use their stuff.
Rust can be very safe, but you should really program on all levels. Check and abstract common low level magic you need into a libray and write extensive tests for it. Then use it from a high level.
Unsafe blocks are not per se a bad thing (in fact, they are needed to solve certain things efficiently), just make sure you really know why you need it and what you do within it.
People unfamiliar with Rust and even some people familiar with Rust frequently get confused about use of unsafe. Even in the case of this actix debacle there's a lot of misunderstanding circulating. There's nothing wrong with using unsafe code, and it's frequently necessary for things like explicit SIMD or invoking compiler intrinsics. The Rust community (barring maybe some of the lowest of low-information individuals circling around Reddit/HN) are not going to get on anyone's case about using unsafe. But using unsafe isn't a get out of jail free card, and it doesn't allow you to break any of Rust's invariants, it is used to indicate that the programmer has ensured that the invariants are upheld, rather than the compiler. If you use unsafe to violate an invariant then you have written a bug and introduced UB. Is anyone going to get on your case about writing bugs in your open source project? Probably depends on how popular the project is and how you portray it. If you advertise it as production-ready and it gets popular and then it is discovered that it'd riddled with UB bugs people are probably going to be annoyed.
Also, the internet being the way it is, if you use unsafe correctly to do things that you could have done with safe code, where the compiler would have produced the same result either way, rude internet people will probably be rude to you.
We use Rust for HFT. We do that, in part, because it means we don't have to worry about segfaults or UB in the software we develop. HFT code may not be exposed to as much danger as a web service, but there may well be more money riding on it.
I'm not suggesting it's a bad choice for HFT, just wondering if the community would be more accepting of a HFT library that used unsafe (assuming for some reason somebody decided to open-source a HFT library), compared to a web server.
Very curious where you work, because there's only really a handful of major places doing HFT (as opposed to algorithmic trading) and haven't heard of Rust being used at any of them.
To be clear before I respond, I believe there were some overzealous individuals that were concerned about unsafe usage in the project and did a very poor job of communicating with the maintainer. This follow up post drives at the heart of that: https://raphlinus.github.io/rust/2020/01/18/soundness-pledge...
Now to your question. Rust is a language that allows you to express correct programs in a number of contexts. Memory safety and concurrent modification free code being two chief ones. What people are constantly proving is that unsafe escape hatches for performance reasons are not as regularly required as similar C implementations would make you believe.
In games and HFT, I would argue having correct programs is as important as any other area of development. That’s the gamble, that you no longer need to make the trade off of safety vs. correctness. But, for expediency of development I could understand why folks see this as a trade off that is required, but that’s really just about the maturity of the language ecosystem in those areas.
Ideally any unsafe code will be contained inside a crate and never be exposed to users of that crate. The crate says “I’m giving you these safe APIs and if you use them, then your code will be safe”, it’s a contract. The point being, for games and HFT, there are many cases where you’re interacting with hardware to improve performance, the big question then becomes, can those hardware abstractions offer safe APIs such that any code built on top of them would be safe. I’d argue Rust proves that this is possible to do, and in answer to your ultimate question, that yes, even in these contexts, Rust would allow developers of those types of programs to build more correct software.
I think this picture of how HFT and games work doesn't have much connection to how it actually does. In these industries you can't just get all or even most of the high performance stuff you need off the shelf for a variety of reasons. You have to write a lot of it yourself, and likely you'd need to write quite a lot of unsafe code (certainly in HFT, speaking from experience).
Rust "fearless concurrency" doesn't cover static deadlock prevention or livelock prevention or misuse of C++11 memory model even if you only use safe code.
It's hard to say. I think a lot of the Rust community actually hails from more of the web world, where security is rightfully a big concern, and the that's where actix was positioned. So maybe with something like HFT it wouldn't be as big of a deal.
On the other hand, very little of the Rust community actually does HFT, or understands the trade-offs. In HFT code, "caching pointers" to just about everything is extremely common, because it's super fast. So you'd be using unsafe a ton. If people got a glimpse of some of the code, I have a strong feeling that some subset would start lecturing (unironically, engineers with a decade of experience in HFT) about safety vs perf trade-offs, and ask "have you actually benchmarked", etc.
I don't think I've seen another situation where the arguably premier framework for some language was so contrary to the language's purpose and community goals.
It would be like building a GraphQL framework that serialized all data as Base64'd XML inside a single field, or perhaps if the biggest Burning Man art car was police-themed.
I feel bad for the maintainer and how the community treated him, but I think his reaction was incredibly self-destructive.
I'm a little worried about the professional ramifications he'll face. His employer is definitely aware of him burning down all of his open source code. That's got to make for awkward conversations with his team, peers, and manager. It's also going to make future job hunting weird if that subject is broached.
How did this escalate to this point? Why couldn't people be nicer to him? Even if the unsound arguments are true, there are better ways to offer constructive criticism. People needlessly backed this man into a corner from which he saw this as the only solution. He's going to be dealing with this for some time. :(
Why do you think this reflects badly on him? He deleted some repositories that he made in his spare time? It wouldn't affect my decision to hire him negatively, and the experience that he demonstrated with the project is still a massive positive.
I think it was the wrong way to disengage from the project and community. Deletion and removal is destructive. He could have easily changed the README and archived the project, but he went out of his way to destroy it.
Without knowing him, I'd worry he'd do that in other organizations he's a member of. What if he has a fight at work? Will he delete stuff or leave in a hurry without making arrangements for other maintainers?
I'm not saying he would do these things or that he's a bad person, it's just something I'd be cautious of given his response to this. If I were his manager or coworker I certainly wouldn't fire him, but I would talk to him about it.
As for next steps, I think the maintainer should undo the deletion, apologize for the rash response, thank the sane members of the community for their appreciation, and leave a message that he's disengaging for awhile (it could be forever). That would be the perfect way to go about it. It doesn't leave a bad taste, and it's an overall good look. It's the high road.
I still feel incredibly bad about how the community treated him. He was doing amazing work for all of us, and some careless folks berated him needlessly. There are better, more constructive forms of criticism.
35 comments
[ 33.0 ms ] story [ 326 ms ] threadIn which case the "downside" from unsafe code is much less (it's not going to leak an entire database of people's private details to the web), so would people still make such a big fuss about removing it? Especially if removing it involves any performance compromise, which in HFT at least would be unacceptable (or at least politically unacceptable when trying to sell Rust).
If you wrote a game engine in Rust, and open-sourced it, you'd probably get similar grief. Because that's what Rust is largely about. Anyways, certain high performance render applications (browsers, ahem), don't seem to suffer significant penalties.
Also, I'd argue that memory safety/rce protection/etc is crucial in games, particularly ones that are online. HFT running in a contained env? Less so, for sure.
It's a modern language: no #includes, faster compilation (compared to template-heavy C++), nice macros, compile-time reflection (libraries like Serde are really nice), generally nicer stdlib than C++, decent package manager. And it's one of the only languages with RAII/destructors, which to me are one of the best things about C++.
>Also, I'd argue that memory safety/rce protection/etc is crucial in games, particularly ones that are online.
This applies to the server, but not to the graphical game client running on the user's machine, as the client is usually not accepting random inbound connections, instead it just connects to the server.
>This applies to the server, but not to the graphical game client running on the user's machine, as the client is usually not accepting random inbound connections, instead it just connects to the server.
There have been a few demonstrated RCEs in game clients (especially in P2P models which many modern games use).
You should profile/benchmark that with a couple thousand lines of code... C++ can be slow to compile (although it isn't always), but so can Rust.
I will add to your list that Rust generally has nicer error messages.
However from experience I can say that you can use Rust against the grain, which will result e.g. in constant fights with the borrowchecker, weird solutions to get around the typesystem and a ton of unsafe (=trustme) blocks.
Rust can do a lot for you, you just have to think a little more about a programs architecture and don't force paradigms like OOP onto it.
Whatever you're doing, you should care about soundness. In games and HFT unsound code leads to segfaults or undefined behavior, not necessarily security issues.
There are a handful of places where safety guarantees can (in some cases) actually cause performance issues. Most common would be iterators created from nested adapters over slices of known length. But that's the kind of thing unsafe exists for and no one is going to get fussy about you using the escape hatch for the manual checks.
But most of the soundness guarantees of rust can't be avoided without a bit of effort even within unsafe blocks, and don't come with performance hits. That is because the core promise of borrow checker is that it guarantees you will not create multiple mutable aliases of the same data through your program logic (you can only really do this with manual pointer hackery, edit: or interior mutability primitives).
That's what omits things like iterator invalidation and use after move/free from being composable in the language itself, and they're things that asan and valgrind can't really catch unless you're fuzzing the crap out of your program during testing. But that's a lot of effort and developer time sitting around to make a best guess about something not happening that doesn't have performance impacts.
But really at the end of the day, soundness, memory safety, secure, these are correlated but different concepts that most programs have to deal with in one way or another.
People should be allowed to be free of harassment. I think everyone would have been better off in this case if the individuals who were so concerned about the unnecessary safety, forked Actix and had a SafeActix, that was maintained without the usage they were concerned about.
If the maintainer isn’t going to accept your patches, then it’s time to decide how to move forward without needing to resort to harassment.
I always like to translate unsafe in my head to "trust me I checked this very thoroughly" — if there are indicators that the author doesn't deserve that trust, I just won't use their stuff.
Rust can be very safe, but you should really program on all levels. Check and abstract common low level magic you need into a libray and write extensive tests for it. Then use it from a high level.
Unsafe blocks are not per se a bad thing (in fact, they are needed to solve certain things efficiently), just make sure you really know why you need it and what you do within it.
Also, the internet being the way it is, if you use unsafe correctly to do things that you could have done with safe code, where the compiler would have produced the same result either way, rude internet people will probably be rude to you.
Now to your question. Rust is a language that allows you to express correct programs in a number of contexts. Memory safety and concurrent modification free code being two chief ones. What people are constantly proving is that unsafe escape hatches for performance reasons are not as regularly required as similar C implementations would make you believe.
In games and HFT, I would argue having correct programs is as important as any other area of development. That’s the gamble, that you no longer need to make the trade off of safety vs. correctness. But, for expediency of development I could understand why folks see this as a trade off that is required, but that’s really just about the maturity of the language ecosystem in those areas.
Ideally any unsafe code will be contained inside a crate and never be exposed to users of that crate. The crate says “I’m giving you these safe APIs and if you use them, then your code will be safe”, it’s a contract. The point being, for games and HFT, there are many cases where you’re interacting with hardware to improve performance, the big question then becomes, can those hardware abstractions offer safe APIs such that any code built on top of them would be safe. I’d argue Rust proves that this is possible to do, and in answer to your ultimate question, that yes, even in these contexts, Rust would allow developers of those types of programs to build more correct software.
On the other hand, very little of the Rust community actually does HFT, or understands the trade-offs. In HFT code, "caching pointers" to just about everything is extremely common, because it's super fast. So you'd be using unsafe a ton. If people got a glimpse of some of the code, I have a strong feeling that some subset would start lecturing (unironically, engineers with a decade of experience in HFT) about safety vs perf trade-offs, and ask "have you actually benchmarked", etc.
It would be like building a GraphQL framework that serialized all data as Base64'd XML inside a single field, or perhaps if the biggest Burning Man art car was police-themed.
I'm a little worried about the professional ramifications he'll face. His employer is definitely aware of him burning down all of his open source code. That's got to make for awkward conversations with his team, peers, and manager. It's also going to make future job hunting weird if that subject is broached.
How did this escalate to this point? Why couldn't people be nicer to him? Even if the unsound arguments are true, there are better ways to offer constructive criticism. People needlessly backed this man into a corner from which he saw this as the only solution. He's going to be dealing with this for some time. :(
Without knowing him, I'd worry he'd do that in other organizations he's a member of. What if he has a fight at work? Will he delete stuff or leave in a hurry without making arrangements for other maintainers?
I'm not saying he would do these things or that he's a bad person, it's just something I'd be cautious of given his response to this. If I were his manager or coworker I certainly wouldn't fire him, but I would talk to him about it.
As for next steps, I think the maintainer should undo the deletion, apologize for the rash response, thank the sane members of the community for their appreciation, and leave a message that he's disengaging for awhile (it could be forever). That would be the perfect way to go about it. It doesn't leave a bad taste, and it's an overall good look. It's the high road.
I still feel incredibly bad about how the community treated him. He was doing amazing work for all of us, and some careless folks berated him needlessly. There are better, more constructive forms of criticism.
Good call, fafhrd91! C'mon, people, it's only software, try to understand each other and be civil.