steveklabnik
a day ago
This is a very interesting post! One takeaway is that you don't need to re-write the world. Transitioning new development to a memory safe language can bring meaningful improvements. This is much easier (and cheaper) than needing to port everything over in order to get an effect.
gary_0
20 hours ago
In fact, these results imply that the benefits of re-writing the world are limited in terms of security. This raises the cost-benefit ratio of keeping mature legacy code and only using memory-safe languages for new code.
This also implies that languages and tooling with robust support for integrating with unsafe legacy code are even more desirable.
Xylakant
15 hours ago
Essentially, this has been Rusts value proposition from the outset - build a language that you can integrate into other codebases seamlessly, hence the choice of no runtime, no garbage collector etc. Bindgen (https://github.com/rust-lang/rust-bindgen) and similar tooling were around essentially since day one to assist in that.
It’s the only approach that has any chance of transitioning away from unsafe languages for existing, mature codebases. Rewriting entirely in a different language is not a reasonable proposition for every practical real-world project.
dadrian
15 hours ago
Rust had to be dragged kicking and screaming into integration with other languages, and its C++ compatibility is a joke compared to Swift.
It's absolutely true that you need integration and compatibility to enable iterative improvements, but Rust historically has been hostile to anything besides unsafe C ABI FFI, which is not suitable for the vast majority of incremental development that needs to happen.
Luckily, this is starting to change.
Philpax
13 hours ago
"Hostile" is assigning intent that was not present. C++ ABI integration was and is extremely difficult; you need to be able to fully handle C++ semantics and to target each platform's take on the ABI. Most C++ competitors have struggled with this for much the same reason.
This means that "solving this" requires partial integration of a C++ compiler; it's not a coincidence that the languages with the most success have been backed by the organisations that already had their own C++ compiler.
A much easier solution is to generate glue on both sides, which is what `cxx` does.
bluGill
3 hours ago
If the intent was to interoyerate with c++ then not supporting the api is hostile. I have a lot of code using vector, if I have to convert that to arrays then you are hostile and worse that is new code which per the article makes it suspect
d does support c++ abi. It seems almost dead now but it is possible.
realistically there are two c++ abis in the world. Itanimum and msvc. both are known well enough that you can imblement them if you want (it is tricky)
Philpax
an hour ago
> If the intent was to interoyerate with c++ then not supporting the api is hostile. I have a lot of code using vector, if I have to convert that to arrays then you are hostile and worse that is new code which per the article makes it suspect
It's not hostile to not commit resources to integrating with another language. It might be shortsighted, though.
> d does support c++ abi. It seems almost dead now but it is possible.
That was made possible by Digital Mars's existing C++ compiler and their ability to integrate with it / borrow from it. Rust can't take the same path. Additionally, D's object model is closer to C++ than Rust's is; it's not a 1:1 map, but the task is still somewhat easier. (My D days are approaching a decade ago, so I'm not sure what the current state of affairs is.)
> realistically there are two c++ abis in the world. Itanimum and msvc. both are known well enough that you can imblement them if you want (it is tricky)
The raw ABI is doable, yeah - but how do you account for the differences in how the languages work? As a simple example - C++ has copy constructors, Rust doesn't. Rust has guarantees around lifetimes, C++ doesn't. What does that look like from a binding perspective? How do you expose that in a way that's amenable to both languages?
`cxx`'s approach is to generate lowest-common denominator code that both languages can agree upon. That wouldn't work as a language feature because it requires buy-in from the other side, too.
SkiFire13
9 hours ago
> Rust had to be dragged kicking and screaming into integration with other languages
Rust has integration with the C ABI(s) from day 1, which makes sense because the C ABI(s) are effectively the universal ABI(s).
> and its C++ compatibility is a joke
I'm not sure why you would want Rust to support interoperability with C++ though, they are very different languages. Moreover why does this fall on Rust? C++ has yet to support integration with Rust!
> compared to Swift
Swift bundled a whole C++ compiler (Clang) to make it work, that's a complete deal breaker for many.
> Rust historically has been hostile to anything besides unsafe C ABI FFI
Rust historically has been hostile to making the Rust ABI stable, but not to introducing other optional ABIs. Introducing e.g. a C++ ABI has just not been done because there's no mapping for many features like inheritance, move constructors, etc etc. Ultimately the problem is that most ABIs are either so simple that they're the same as the C ABI or they carry so many features that it's not possible to map them onto a different language.
maxk42
5 hours ago
I would like to point out also that C++ is not yet compatible with itself. Even GCC has dozens of C++ features it doesn't implement and it was the first compiler to implement 100% of C++11: https://gcc.gnu.org/projects/cxx-status.html
bluGill
3 hours ago
I have millions of lines of c++. I'd love t use something else but without interoperability it is much harder. If you only write C you are fine. If you write java you want java interoperability, similear for lisp, or whatever your existing code is in.
steveklabnik
8 hours ago
That was created with the intention of being integrated into a very large C++ codebase.
I do agree that they could do more. I find it kind of wild that they haven’t copied Zig’s cross compilation story for example. But this stuff being just fine instead of world class is more of a lack of vision and direction than a hostility towards the idea. Indifference is not malice.
Also, you seem to be ignoring the crabi work, which is still not a thing, of course, but certainly isn’t “actively hostile towards non-c ABIs”.
samatman
6 hours ago
I think they had to get over the knee-jerk reaction that Zig was a, quote, "massive step back for the industry", frowny face.
It seems they have, which is all to the good: the work to make custom allocators practical in Rust is another example. Rust still doesn't have anything like `std.testing.checkAllAllocationFailures`, but I expect that it will at some future point. Zig certainly learned a lot from Rust, and it's good that Rust is able to do the same.
Zig is not, and will not be, a memory-safe language. But the sum of the decisions which go into the language make it categorically different from C (the language is so different from C++ as to make comparisons basically irrelevant).
Memory safety is a spectrum, not a binary, or there wouldn't be "Rust" and "safe Rust". What Rust has done is innovative, even revolutionary, but I believe this also applies to Zig in its own way. I view them as representing complementary approaches to the true goal, which is correct software with optimal performance.
steveklabnik
5 hours ago
While Patrick played a critical role in Rust's history, he said that years after he stopped working on Rust. I haven't seen people still involved share strong opinions about Zig in either direction, to be honest.
I've known Andrew for a long time, and am a big fan of languages learning from each other. I have always found that the community of people working on languages is overall much more collegial to each other than their respective communities can be to each other, as a general rule. Obviously there are exceptions.
nindalf
12 hours ago
> Rust had to be dragged kicking and screaming into integration
On what basis do you make this flagrant claim? There is certainly an impedance mismatch between Rust and C++, but "kicking and screaming" implies a level of malice that doesn't exist and never existed.
Such a low quality comment.
bobajeff
10 hours ago
>has been hostile to anything besides unsafe C ABI FFI
As opposed to integrating with a whole C++ frontend? Gee, I wonder why more languages haven't done this obvious idea of integrating a whole C++ frontend within their build system.
pjc50
13 hours ago
Rewrites are so expensive that they're going to be very rare. But incremental nibbling at the edges is very effective.
I wonder if there's a "bathtub curve" effect for very old code. I remember when a particularly serious openssl vulnerability (heartbleed?) caused a lot of people to look at the code and recoil in horror at it.
Ygg2
19 hours ago
From security perspective I agree but what if you want to be rid of GC or just reduce your overall resource consumption?
pjmlp
17 hours ago
Learning how to actually use the language features that don't rely on GC, like on Swift, D, C#, Linear Haskell, Go, Eiffel, OCaml effects... is already a great step forward.
Plenty of people keep putting GC languages on the same basket without understanding what they are talking about.
Then if it is a domain where any kind of automatic resource management is impossible due to execution deadlines, or memory availability, Rust is an option.
elcritch
17 hours ago
Well Rust also has certain aspects of “automatic resource management”. You can run into execution deadline issues with allocation or reallocated (drop) in Rust. The patterns to avoid this in critical areas is largely the same in any of the languages you listed.
Though I like using effect systems like in Nim or Ocaml for preventing allocation in specific areas.
pjmlp
16 hours ago
You can even run into execution deadlines with malloc()/free(), that is why there are companies that made business out of selling specialized versions of them, and nowadays that is only less of a business because there are similar FOSS implementations.
The point is not winning micro-benchmarks games, rather there are specific SLAs for resource consumption and execution deadlines, is the language toolchain able to meet them, when the language features are used as they should, or does it run out of juice to meet those targets?
The recent Guile performance discussion thread is a good example.
If language X does meet the targets, and one still goes for "Rewrite XYZ into ZYW" approach, then we are beyond pure technical considerations.
throwaway2037
8 hours ago
> The recent Guile performance discussion thread is a good example.
Sounds very interesting. Can you share a link?itishappy
3 hours ago
redman25
9 hours ago
Most GC languages give you limited control over "when" garbage collection or allocation occur. With non-GC'd languages you can at least control them manually based on data structure choice (i.e. arenas), lifetimes, or manual drops.
throwaway2037
8 hours ago
Do you count Python, where the ref impl (CPython) uses reference counting, as a GC language? If yes, you have a better idea when GC will occur compared to non-deterministic GC like Java/JVM and C#/CLR.
neonsunset
8 hours ago
.NET has a few runtime knobs to control GC behavior at runtime:
GC.TryStartNoGCRegion - https://learn.microsoft.com/en-us/dotnet/api/system.gc.tryst...
GCSettings.LatencyMode - https://learn.microsoft.com/en-us/dotnet/standard/garbage-co...
The latter is what Osu! uses when you load and start playing a map, to sustain 1000hz game loop. Well, it also avoids allocations within it like fire but it's going to apply to any non-soft realtime system.
neonsunset
8 hours ago
These are not mutually exclusive. In some GC-based languages these techniques are immediately available and some other languages take more abstracted away approach, relying more on the underlying runtime.
nine_k
18 hours ago
Your engineers are usually your most expensive resource. Developing software in Typescript or even Ruby is a way to get to the revenue faster, having spent less money on development. Development cost and time (that is, the opportunity cost) are usually the most important limitations for a project where the defect rate does not need to be extremely low (like in aircraft control firmware). Rust saves you development time because less of it is spent fixing bugs, but often would pick it not because it saves you RAM and CPU cycles; Haskell or, well, Ada/Spark may be comparably efficient if you can wield them.
hyperman1
17 hours ago
This is true, but there is a crossover point where engineers spend more time understanding existing code than writing new code. Crossing it is typically a point where more static languages with more built in checks become cheaper than more dynamic code. In my experience, it takes about a year to reach this point, less if you hire more people.
Ygg2
15 hours ago
To a point. Let's say you're optimizing a backend written in TS on Amazon, sure it's cheaper to hire guys to optimize it, but at some point it won't be. Either you need some really high class talent to start optimizing shit out of TS or you can't scale as fast as before.
Didn't something similar happened at Discord. It was Go if I recall.
nine_k
10 hours ago
Indeed, the larger the scale, the more impact (including the costs of operation) a piece of software has. In a dozen^W^W OK, a thousand places where the scale is large, engineers shave off a percent or two of resource usage, and this saves company money.
But most places are small, and engineers optimize the time to market while remaining at an acceptable levels of resource consumption and support expenses, by using stuff like next.js, RoR, etc. And that saves the company money.
There is also a spectrum in between, with associated hassles of transition as the company grows.
My favorite example is that eBay rewrote their backend three times, and they did it not because they kept building the wrong thing. They kept building the right thing for their scale at the moment. Baby clothes don't fit a grown-up, but wearing baby clothes while a baby was not a mistake.
Ideally, of course, you have a tool that you can keep using from the small prototype stage to the world-scale stage, and it lets you build highly correct, highly performant software quickly. Let's imagine that such a fantastical tool exists. To my mind, the problem is usually not in it but in the architecture: what's efficient at a large scale is uselessly complex at a small scale. The ability to express intricate constraints that precisely match the intricacies of your highly refined business logic may feel like an impediment while you're prototyping and haven't yet discovered what the logic should really be.
In short, more precision takes more thinking, and thinking is expensive. It should be applied where it matters most, and often it's not (yet) the technical details.
pjmlp
10 hours ago
Indeed, however I would vouch those rewrites have been more a people issue than technical.
Apparently there is unwillingness to have "high class talent", while starting from scratch in a completly different programming language stack where everyone is a junior, is suddenly ok. Clearly CV driven development decision.
Secondly, in many cases, even if all optimization options on the specific language are exhausted, it is still easier to call into a native library in a lower level language, than a full rewrite from scratch.
geodel
an hour ago
My takeaway was if it is our server/cloud cost we will try to optimize the hell out of it. When it is user / client side cost, fuck the user, we will write the crappiest possible software in JS/TS/Electron whatever and ask user upgrade their machine if they whine too much.
And totally agree about CV driven development. All these rewrite articles looks like they are trying to convince themselves instead if intelligent readers about rewrites.
steveklabnik
19 hours ago
Then you should use the language that’s memory safe without GC.
Ygg2
18 hours ago
Yes, I'm saying in those cases it does make some sense to rewrite it in Rust.
UncleMeat
11 hours ago
If you have a codebase that has no security implication and won't receive significant benefit from improved productivity/stability from a more modern language, almost certainly not.
Such projects exist. That's fine.