To put this in perspective, though: increasing the number of people paid to work on the Rust compiler by 10x would only mean hiring about 25 people. Compared to the size of the projects that are starting to depend on Rust, that's a rounding error.
To put this in perspective, though: increasing the number of people paid to work on the Rust compiler by 10x would only mean hiring about 25 people. Compared to the size of the projects that are starting to depend on Rust, that's a rounding error.
Dlang compiles quickly not because the language is simple, but because the compiler authors care about compilation speed:
Lexer skips four spaces at once https://github.com/dlang/dmd/pull/11095
Optimize core logic to 7x compilation speed of language feature https://github.com/dlang/dmd/pull/11303
Cache rarely used types to improve memory locality https://github.com/dlang/dmd/pull/11363
Though TBH I'm not an expert on the compiler and I'm not confident I know the root problems or the solutions.
I'm referring to the rust-analyzer work, which is effectively an outside-in re-write of the compiler, if you squint at it right.
At the end of the day, rustc is a very large codebase, and has already undergone major architectural changes, and will be undergoing even more. It is not fast to steer a large ship in a new direction, but that is what is happening.
See https://pbs.twimg.com/media/ENC1ls6XYAEdKkv?format=jpg&name=... for a time I ran https://github.com/erikbern/git-of-theseus on the rustc codebase. Thank goodness Rust is such a good refactoring language.
If anything, the cranelift stuff is less radical. Doesn't require any architecture changes, "only" involves implementing the backend API.
https://github.com/bjorn3/rustc_codegen_cranelift/issues/743...
dA lot of work is being done to address these issues. The big projects I'm aware of are a move to a query-based compiler (which should improve incremental build times) and the new cranelift backend, which should dramatically speed up debug build times.
Since Rust 1.38 (https://blog.rust-lang.org/2019/09/26/Rust-1.38.0.html#pipel...) that's no longer the case: "To compile a crate, the compiler doesn't need the dependencies to be fully built. Instead, it just needs their "metadata" (i.e. the list of types, dependencies, exports...). This metadata is produced early in the compilation process. Starting with Rust 1.38.0, Cargo will take advantage of this by automatically starting to build dependent crates as soon as metadata is ready."
The C++ version still wins by several minutes on a Asus 1215B.
And I test it on that hardware on purpose, because I should not have to buy a top class desktop to achieve usable compile times similar to other AOT compiled languages.
However, I also admit that what is missing is having a backend that favours debug workflows, which do exist just aren't yet there.
For me D is what .NET (thus C#) should have been if the Ext-VOS project (COM Runtime) decided to go native, instead of embracing J++ and then turning into .NET due to the lawsuit.
But unfortunately D is a tiny community that gets by with small contributions and herding cats is hard.
Is this meant to imply that the Rust compiler authors don't care about compilation speed?
For example, here's the 2017 roadmap, which was authored in 2016 https://github.com/rust-lang/rfcs/blob/master/text/1774-road...
> The edit-compile-debug cycle in Rust takes too long, and it's one of the complaints we hear most often from production users. We've laid down a good foundation with MIR (now turned on by default) and incremental compilation (which recently hit alpha). But we need to continue pushing hard to actually deliver the improvements. And to fully address the problem, the improvement needs to apply to large Rust projects, not just small or mid-sized benchmarks.
We didn't do these sorts of yearly plans before that, but note that it isn't just talking about what should be done then, but the work that was being done on this previously.
However, the commits I linked to describe front-end optimizations. LLVM-based D Compiler and GCC share DMD's front-end.
I've seen some generated code optimizations for DMD's back-end as well, which could get one lightning fast compiles for decent code. (Maybe in the future one could write a JIT that first compiles with DMD then tiers up to LLVM D Compiler or GCC.)
Rust's ownership model, which allows you to write straightforward, non-leaky, non-use-after-free-filled code without a GC, is quite complex at compile time. It's definitely possible to make it faster, but it's definitely a thing Rust does that D doesn't do.
F# is the most pleasant, practical day-to-day programming language that I have personally used. Scala is also quite nice.
Would something similar be possible for Rust, so you still have the ability for correctness for CI and release builds, but allow for fast compilation when necessary or desired?
1) Technical debt in rustc producing large amounts of LLVM IR and expecting LLVM to optimize it away
2) generic monomorphization producing vast amount of IR
IIRC.
Yes. The `mrustc` alternative implementation doesn't do things like borrow checking, it assumes the source is "correct".
> [skipping typechecking would] allow for fast compilation when necessary or desired?
The real expenses in a "release" compilation pipeline are in the optimisation passes and codegen, so the gains are mostly in avoiding optimisations (debug build) or avoiding codegen entirely (`cargo check`).
For instance on the latest ripgrep head on my machine:
* cargo check takes ~200s user
* cargo build (debug) takes ~300s user
* carbo build --release takes ~900s user
Outside the kernel, I don't think it's going to be true for Android or Windows.
Assuming no unsafe blocks, rust's type system eliminates entire classes of memory safety errors. It fundamentally eliminates data races. It eliminates large swaths of logical errors, due to its use of algebraic data types, and strong type enforcement. No null pointers, explicit error handling, and no undefined behavior.
It boggles my mind that people will balk at compile times for rust, but then not even bat an eye at their C++ testkit that runs for 8+ hours, primarily checking for errors that rust would never let you make in the first place.
To a first approximation, rustc is slow because it generates terrible LLVM IR, and relies on a number of slow LLVM optimization passes to smooth that IR into something reasonable. As far as I can tell this is entirely a result of not having the necessary engineering resources to throw at the problem; Mozilla has a limited budget for Rust, and needs to spread that budget across not just the compiler toolchain, but the language and ecosystem.
Brian Anderson's been working on a blog post series that covers Rust's slow compile times in more detail, if you're curious: https://pingcap.com/blog/tag/Rust
If the focus is entirely on reducing compile times, it can very quickly lead down a path that limits runtime performance. There is so much potential for increased runtime performance in strongly typed languages, due to the guarantees made by the type system. It allows for analysis and reasoning that not just enables micro-optimizations but also macro-optimizations across entire codebases. Entire theses have been written describing optimizations that rely on immutability alone, and we haven't even touched so many other possibilities that rust's design enables (such as the ownership system).
I'm fairly familiar with the project to work on the LLVM-IR code emitter. If the focus is on reducing the complexity and cruft of the LLVM-IR emitted, that's a win all around (because you get faster code and faster compile times). I just hope that reducing compile times doesn't become the core objective, because that eliminates a lot of future potential.
A. Yes, as you say, taken from a distance and considering the whole development lifecycle from idea to shipping, "compile time isn't really that bad for rust when you consider what it actually does for you".
B. However, -during- development, you want compile speed, regardless of all the benefits. I don't know about you, but I have a hard time rationalizing "it's okay, rustc is doing many things" at that moment. I just want it to be faster, and as OP mentioned, I hope there's a future where companies / sponsors get to "hiring about 25 people" to crunch and improve things noticeably (and I will do more than hope, I already donate money to Ferrous Systems to improve rust-analyzer, and will donate if a "make rust faster" fund asks for it). Your argument sounds to me a bit like "who cares about making Python faster? It's just glue". To which I answer: maybe (though not always), but even then but I'll take faster glue anytime :) .
To sum up: rust being already awesome and being "fast given all the thing it does" doesn't mean it shouldn't be faster, and doesn't mean speaking about it is futile.
Generally speaking, if you are using incremental compilation, Rust is fast enough for development. It could be better, especially on large projects, but I haven't found it to be an issue generally. There are a bunch of improvements that could still be made. The LLVMIR issue mentioned above is one of them. But also, why do we have to rely on a code emitter at all? In development mode, the type checker should be incremental, synchronous, and fast...but the code emitter could be relatively slow as long as it is asynchronously coupled to the type checker.
But relentlessly pursuing the path of compiler performance can be a bad route to take, because it invariably leads to stagnation in compiler capabilities. I'd gladly accept a 10x increase in `opt-level=3` compile times if it meant 10% faster runtime performance. I'd gladly accept a 10x increase in `opt-level='z'` compile times if it meant a 50% decrease in binary sizes. We can't get to those capabilities if those possibilities are squashed by concerns about compile times.
A basic technique to parallelize sections is to split a project into modules. Is this not an option for the linux kernel?
The problem is that when you have module A depending on module B, rustc doesn't do a good job of compiling A and B in parallel. In contrast, in C/C++ you can handcraft your header files to ensure that A and B compile in parallel.
However C++ is also now looking at parallelization opportunities for modules, which is a similar situation as crates.
It is much better at this than C++.
For example, change a trait in your Rust library, and recompile the tests, and compare that with changing a type in, say, range-v3 (or any other C++ header-only library).
In C++, recompiles take pretty much the same time as clean builds (for range-v3, exactly the same time). In Rust, they are infinitely faster (100000x faster, depending on the project, but essentially almost instant, in contrast with initial compiles).
So for development at least I'll pick Rust over C++ every day. I only do an initial compile once, but I edit and recompile a lot, and that's the bottleneck that I really care about.
(Same with C btw, add a new API to a commonly use C header and re-compile, and you end up re-compiling the world, while from Rust, you just re-compile the part of the crate where the new API was added, and since no downstream crates use it, that's pretty much it - instant change).
Citation needed ?
I know at least 20 people being paid to work on the Rust compiler, which crank's your 10x number from 25 to 200. And this is only the people I can come up with from the top of my head.
The problem starts when Rust throws a ton of IR at LLVM. The current focus is on adding optimizations in Rust at higher level (MIR) so that it would cause less work for LLVM.
There is another major problem, which is that rustc/cargo do not do a good job of compiling crates in parallel when one depends on the other.
There may well be other problems too.
On the other side, imagine you can even reduce the "ton of IR" tenfold but if the compilation is sequential, the tenfold speedup is fixed even if you have 32 or 320 cores.
In general, allowing for parallel compilation is much more important topic, and it's worth even redesigning language to make that more achievable.
Which also doesn't mean that producing "ton of IR" is a good thing. But working on allowing maximum parallelism is more fundamental. Also, discovering algorithms to allow all compiler passes as effective as possible is important for something to reach wider usability. But Rust must also get to achieve its promises of being "safer" in the scenarios where C is otherwise used, and I time and again see a lot of "unsafe" keywords in the sources wherever I see some implementation of anything fundamental.
On the other hand, reductions in the amount of computation needed mean you get a faster build for the same resources, or a similar speed build for cheaper.
Depending on your circumstances, one of these things (speed vs. cost) might be much more important than the other. We cannot forget about either.
Trying to get a program to quickly do the exact same thing over and over again is a colossal waste of resource.
You can prioritize, but that makes the rest a matter of “when” not if.
It can be hard to tell from the outside if someone is avoiding a problem because they don’t want to solve it, or because they are hoping for a more inspired solution. Tackling a problem when all the options are bad may block another alternative when it does finally surface. I’d lump this in with irreversible decisions and the advice to delay them to the last responsible moment.
Who know what internal plumbing has to be moved around to make the compiler more incremental, parallel, or both.
But trying to constant-factor optomize O(code I didn't change) is a ridiculous approach that needs justification, and the burden of proof is on those that advocate it. Yet, this seem to be the default thing people beg for.
Switching to incremental is hard programming, and that's why it hasn't happened overnight, but at least it is an algorithmically sane approach.
And are you going to pay for the "rounding error" or just expecting someone to pay for millions a year for your idea?
As for who pays for it: that's a tricky issue! But if we get into a situation where (for example) 10,000 developers spend an hour a day waiting for builds, we know 50 developers could fix the issue in a year, but that doesn't happen because we can't figure out how to structure it economically --- that would be a failure of organizational imagination.
"That volcano looks like it's becoming active, maybe some sensors could give us an early warning of problems" - Are YOU going to pay for your little "idea"??? Then WHO IS?
"That tree is getting dangeoursly high, it's at risk of falling down in a big storm this winter, maybe we could get it cut down before that" - Are YOU going to pay for it?!
"Dumping raw sewage in the river is making people sick, treating it first would take a small amount of space and a small fraction of the council's existing budget" - and you want to TAX ME for YOUR clean river, I suppose?!
As if OP is the only person who would benefit, as if automatically assuming the worst possible intent for who would pay for it, and as if "who would pay" is the first and only thing worth demanding an answer to, before even having a discussion about whether it's worth doing at all - and which of many ways it might be done.
For the lifetime of a binary, compilation time is like 0.000001% of its existence.
I’m more than happy to wait longer compared to other languages (even zero time at all with scripting languages) while cargo does it’s thing.
Dev reason: tight feedback loops are encouraging, and make it easier to build momentum. I hate being deep in a problem then having to "wait" for a compile.
Comparing compile time to run time is rather strange, but compared as a percentage of a developer’s time, it’s very obvious why people are worried about it.
But more often than not, businesses don't know how their developers spend their time. So as such, they optimise for results. The business doesn't care how you spend your time, as long as by the end of Sprint/Deadline/Whatever you have a result and/or a reason why not. And I'd bet some money that the reason will very rarely be "my compiler took to long".
From a developer standpoint, I understand better (mainly because I'm a developer). But it still lacks a bit: So I started using Rust and I have a long history with C. The first compile with Rust takes very long (because of loading all dependencies), but afterwards it is slower than C, but it's okay. In return you get a lot of extra safety for your program, it's basically time you spent on your C program to fix all those nitty gritty memory safe optimisations and making sure there's no dangling pointers and free(NULL) errors. Of course with experience, these get less and less, but there's always risk. Nobody is perfect.
For me as a developer, it's more of a shift in my thinking - which is, to be fair, hard to enforce on people and can only come from oneself. But now that I have a compiler which supports me handling memory and pointers, my mind is more at ease. It does these things I spend time debugging on for me (most of them, not all) and in return for longer compile time, I save development/debugging time. At first it feels a bit less productive, since you are just sitting around watching your compilation (there's an XKCD for that https://xkcd.com/303/), but you could also spend this time writing documentation, reading up on something or just grabbing your coffee (or leave the office and check in tomorrow). Things you would do anyways, it's just a matter of how you mentally approach it.
I think the downside only comes when you want it to be negative, or when you're still transitioning.
I don't think there are 25 people qualified to do that work looking for jobs. It's not something you can just throw money at, you need really qualified people to do that kind of work. Those people are in very high demand.
Yes, most of them are employed. Some are under-employed. Some are well employed but might be keen to work on a project this important.
Second, the compiler team has put a ton of effort into mentorship infrastructure, and you can go from not knowing a ton to being a productive member of the team with their help. It "just" takes time and desire to do it.
Sure, there are probably some projects for which if the primary author leaves, their coworkers will drop it or rewrite it in another language, but for others the management will realize what a liability it was to have all of their eggs in that one basket and they’ll have to hire 2 to replace them.
If you steal 25 to work on the kernel, you will likely see 25 open reqs to replace them. And more people will work with languages that they have seen reqs for.
I'd love to learn about compilers by working on an actual real world compiler, but I really only know high level details about how different components fit together. I also don't have a formal CS education, although I am currently working as a senior level data engineer. Not sure if that is the sort of person they are looking to mentor.
Just find one that you'd like to work on, write that you are going to work on it, and start doing the work, and asking lots of questions.
Or work on getting what Rust gives you in a different language that isn't Rust (maybe entirely new, maybe not[1]).
One underdiscussed thing about Rust is that it's so clearly a byproduct of the C++ world. And the most disappointing thing about Rust is that it probably won't ever be seen as a prototype that should be thrown away.
I'm into Rust, so I guess I assumed it was common knowledge that it was originally written to be like OCaml with better concurrency, and that one of the early goals was to replace C++ in Mozilla code.
But, language-wise, I don't even see that much similarity with C++ except for the philosophy of zero-cost abstraction and the trivial syntax-style of generics being <>.
i hope you don't have this kind of attitude in real life, because it instantly makes you look like an pretentious prick and loose any credit. Your original comment made me curious, and this one loose any interest in what your point of view actually is.
(fyi : HN is (mostly) a developer community with usually knowledgeable people working in the field. if you don't think explaining yourself here is worth it, i have no idea where you think you're going to have the opportunity to give your opinion)
Yeesh. I don't even know what attitude you're referring to. You've set out to give some life advice, but do you know how real life conversations work? Can you understand that my response will differ greatly depending on what the answer to that question is? It's pretty normal for dialogues to be... dialogues, which includes checking in with each other instead of monologuing based on a lack of shared agreement.
> if you don't think explaining yourself here is worth it
Once again, what are you even talking about? You're responding to something you've imagined I've said or something you want to attribute to me, not what I've actually said or am thinking.
Can you wait for ragnese's reply and then my response before going off the deep end?
> Please respond to the strongest plausible interpretation of what someone says, not a weaker one that's easier to criticize. Assume good faith.
Ironically, by assuming bad faith and a condescending tone in the comment you responded to, you've made a legitimately condescending comment.
Just be warned that most of what you'll see is comments by banned users. Occasionally we get emails from people who don't realize that and somehow assume that moderators are condoning the worst dreck that appears there.
I did write C++ code for about 7 years. It was mostly C++98 and C++11.
Since then I've also done a fair bit of Rust. I'm also very familiar with Swift, Kotlin, Java, some lisps, JS, Go, and a few others. So I have enough breadth in language experience for any compare/contrasts you'd like to do.
Thanks, that was actually the right answer! (And those assuming otherwise are not just getting the wrong answer, but I'll point out are breaking the rules[1] here, too.)
The C++-to-Rust background is what I suspected—but the reason had nothing to do with being dismissive about not having the right buzzwords to prove you're smart and well-rounded. (This isn't a job interview, folks, geez.) My instinct was a presumption of deep familiarity.
When I mention Rust having the marks of a being from the C++ world, I'm referring to a property of the language that it shares with Swift. When you say you don't see much similarity, my suspicion is that your first consideration is language semantics and the new affordances, and so when you think of Rust and C++, you're seeing foremost all the ways that they're different, rather than seeing the things that they share. I saw where Hejlsberg once said that he doesn't get why people draw comparisons between C# and Java, and then gives a list of reasons—where those reasons show that his main focus is similar, i.e. he focuses on the way that they differ (and maybe in his case, all the things that he "fixed" with C# in comparison). One of your sibling commenters writes that "Rust is an ML-family language dressed in a C-family syntax", but that's a little off the mark. Rust certainly has a C++-style syntax, but aside from curly braces, idiomatic Rust looks alien when compared to C.
But what property is that?
> I saw where Hejlsberg once said that he doesn't get why people draw comparisons between C# and Java [...]
That's very amusing!
> Rust certainly has a C++-style syntax, but aside from curly braces, idiomatic Rust looks alien when compared to C.
For sure. But I'm still not sure why you say it's from C++ land. It's definitely more like C++ than C, but JavaScript is also probably more like C++ than C. That doesn't mean JavaScript is actually anything like C++, really.
One thing that I thought of that Rust definitely does share with C++ (and C) that other languages (Swift) don't is that you don't have to decide at class definition if a type will be heap allocated or used as a reference vs value, etc. That's decided at the use-site.
Rust feels very very much like C++ to me. All the memory ownership stuff is basically common patterns in modern C++ pulled down into the compiler and enforced.
Also arguing with the compiler about types feels very familiar from C++ :-/.
It sounds like you're arguing that idiomatic Rust looks alien compared to C, which I'd agree with - I'd also argue it's alien compared to C++. But I assume you disagree with that?
This isn't the case, there are tracing garbage collectors implemented as libraries [1][2], and there is consideration being made for supporting tracing GC in the language and stdlib [0]. As well as reference counted GC having been available in stdlib for a long time [3] (similar to C++'s std::shared_ptr)
[0] https://github.com/rust-lang/rfcs/blob/master/text/1398-kind...
[1] https://manishearth.github.io/blog/2016/08/18/gc-support-in-...
That is not really an explicit goal of C++, which is part of the problem rust is trying solve.
That argument would have to not just explain why an improved language is needed, but also why Rust can't evolve into that language via the edition system. It would also have to convince people that whatever benefits the improved language brings justify moving away from the existing crate ecosystem, tool ecosystem, and developer pool, and building new ones (or how you would reuse/extend/coopt them).
(In reality I think the influence of Haskell and even node.js were as important to Rust as C++.)
https://robert.ocallahan.org/2018/10/the-costs-of-programmin...
... to pair with the mbeddr link.
You seem to be at a place where you think of Rust as already entrenched, but I'm at a place where I still see Rust as a proposition—one that could lead to that place, or not if we think better and nix it (following the reasoning above).
> I hope people consider carefully the social costs of creating a new programming language especially if it becomes popular, and understand that in some cases creating a popular new language could actually be irresponsible.
And being widely used is not the same thing as being entrenched, not the same thing as being unable to say, "nice prototype; let's wrap this up now and do it for real this time".
No, that's kind of the sentence I was responding to. Rust is already popular; that horse is out of the barn.
> And being widely used is not the same thing as being entrenched, not the same thing as being unable to say, "nice prototype; let's wrap this up now and do it for real this time".
I don't care to argue about the first clause, but I don't understand how you can argue the latter. Who is going to say "nice prototype; let's discard this?" Do you expect the Rust-using projects to just fold? Do you expect Rust developers to just disappear? Again, it sounds like you don't like Rust, which is fine, but as someone external to the community, why do you think anyone would listen to you about spinning down Rust?
I stand by that blog post, though I recognise it's controversial. I think Rust clearly qualifies as "worth the cost of a new language". There simply wasn't, and still isn't, any other serious contender for safe GC-free systems programming. New contenders will arise but in the meantime lots of projects are doing safe systems programming that without Rust would have been done in C or C++ and would have had to be unsafe.
Are you questioning whether Rust is simply not good enough to be worth using by anyone? Lots of people, including me, have judged that is worth using for us, both before we tried it and after we've put Rust projects into production.
(BTW once again you have implied there is something deeply wrong with Rust that cancels out its benefits, without saying what that might be. That is annoying.)
If someone released a memory-safe, highly concurrent, systems-oriented version of INTERCAL, you recognize that someone might look at that and say, "Gee, I don't think that's really worth using", and the comment's lack of detail doesn't nullify the substance of what makes the comment true or not? And an opponent could approach in the same way you are now, with the primary goal of "beating" the other participant—by making it burdensome to respond—and by all appearances do so?
It's not my job to painstakingly prepare a perfect, incontrovertible response for a hostile adversary, particularly since absolutely nothing would come of that time investment. If your idea of success is the sound of all your colleagues telling yourselves that you won the conversation and you're on the right track and nothing needs to change because there really aren't any issues... then, hey, that's just fine.
That simply isn't true.
> I reject your claim
That's fine.
>not just tar it by association with C++.
To build on this and your last paragraph: I think it's arguably a feature of Rust that it combines:- A syntax that's highly familiar to the legions of C++ programmers already out there
- A bunch of features C++ has had in the works but that aren't quite there yet (specifically, a proper module system comes to mind)
- Features from ML/OCaml/Haskell, like a first-class option type, first-class (powerful) pattern matching, and an emphasis on immutable-by-default variables
Having this without the cruft of the decades of backwards-compatibility that C++ has had (not without good reason, granted) makes Rust the hard refresh of C++ that I and hopefully others have been waiting for for a while.
C interop is pretty much same as in Rust.
GC is not an issue in modern .NET even for resource-demanding apps running on slow ARM CPUs. Here's an example: https://github.com/Const-me/Vrmac/tree/master/VrmacVideo BTW it consumes non-trivial amount of C APIs like V4L2, ALSA, and audio decoders.
- First-party support for .NET only existed on Windows systems until 2015ish with the release of Rosetta
- Third party support across platforms via Mono never really picked up steam for a number of reasons
- Early on, .NET code, much like JVM code, wasn't in the same league as C++ in terms of performance
- I'd like to be proven wrong on this one, but .NET remains a poor framework to do systems programming in. GC is IMO still a factor because even though modern M&S GCs are impressively performant they still add a degree of unpredictability to your runtime, and sometimes that's not acceptable — so reference counting or something even more basic is preferred, if only for the consistency.
Have you clicked that link? Essentially, I’ve re-implemented parts of ffmpeg’s libavformat and libavcodec in C#. On Raspberry Pi, the software uses 15% of CPU time while playing 12 mbit/sec 1080p video, on par with VLC, while using 20% less RAM than VLC. If that’s not a system programming, then what is?
BTW, I don’t think I allocate any objects on heap while playing the video, therefore no GC is involved, and no degree of unpredictability is introduced. Wasn’t hard at all, just recycling buffers between frames.
Media engine part of the library has 45k lines of code, this is mostly due to the complexity of V4L2 API, and of the MKV and Mpeg4 containers. I wouldn’t call that “simple stuff”.
> you really do need to dynamically allocate and free memory
Memory allocation in .NET ain’t limited to GC.
First of all there’s stack. I use Spans + stackalloc in quite a few places there. Modern .NET even has these `ref structs` where the compiler guarantees they are never accidentally boxed into the heap.
Another thing, no one stops you from using malloc/free, like I did in that class: https://github.com/Const-me/Vrmac/blob/master/VrmacVideo/Aud...
Finally, the mere presence of GC doesn’t affect performance in any way, only usage of GC does. Even for latency-sensitive applications like that media engine it’s OK to allocate stuff on managed heap, as long as it only happens on startup, or otherwise rarely. I allocate quite a lot of stuff on the heap, megabytes, when opening a media file.
Can that ever happen with a language that lots of people use?
• Rust is mainly based on established research and existing languages from 80s and 90s. It's a distilled version of these, not a prototype.
I recommend checking out the first pitch deck for Rust: http://venge.net/graydon/talks/intro-talk-2.pdf
I think the influence of C++ is much more than just the syntax.
It is a low-level programming language after all. Not being explicit about memory would be a bad thing (it almost always is).
It is just that it is typically more useful/powerful in languages that lack a GC (doesn't necessarily need to be that way though, but my impression).
To me, the borrow checker just feels like an additional type layer I have to reason and think about. In that sense, my thinking when reasoning about lifetimes in Rust is a lot more along the same lines I do in Haskell than something I would be doing in C++ (which I refuse to code in, I'm not capable of writing secure C/++ code.)
The question is what happens when programs don't fit those patterns. Inevitably in any large real world application, there are some objects with lifetimes that need to be managed carefully and don't match conveniently with some sort of scope in a program.
With C++, this is where one would use std::shared_ptr, or something else. In rust, there's Rc. But either way, you've now stepped into a territory where object lifetimes and bugs can be messy.
I find that in most cases where ownership patterns don't fit the Rust model, you can abstract the problematic parts into some kind of collection type and hide them in its own crate --- or better still, find an existing crate that does what you need.
The only remotely common case that still doesn't get handled well, in my experience, is the self-referential struct pattern --- when a value needs to contain references to other parts of the same value.
There's a basic reason for that, namely you can't memcpy a self-referential structure while keeping desired semantics. Rust now has a Pin<> feature to mark data that should not be moved in memory, but its use is still unintuitive and IIRC requires unsafe. In many cases one should perhaps avoid references to self-addresses entirely; often they can be replaced by indexes and/or offsets.
You actually can! For instance, consider a struct with two fields: a Vec<T>, and a &T which references one of the elements of the Vec. Moving the struct (which does the memcpy) does not reallocate the Vec, so the reference in the &T would still be valid. But as far as I know there's no way to represent that in safe Rust; the &T in the struct requires a lifetime, and there's no way to represent "the lifetime of the other field" or even "the lifetime of the struct itself" (something like &'self T).
Yeah, you can use an index in my example (replacing the &T by an usize, and looking up on the Vec every time), but it's not a perfect replacement. A reference would always be valid (and always pointing to the same element), while an index can become invalid if the Vec is truncated, or point to a wrong element if an element is inserted or removed before it in the Vec.
Why are you crediting C++ for an idea that is probably much older than it?
In the beginning, I feel like Rust aimed to be a general purpose language, but not anymore. Really the only reason why anyone would consider Rust for a project is if GC was unacceptable. And the amount of complexity in the language just to avoid that is truly staggering.
There aren't that many situations where GC can't be tolerated (and I think some would argue there are zero situations), so I don't actually see Rust as a particularly useful language, and certainly not one in the ML tradition.
Moreover, most zero allocation C code is a total lie. These code bases are littered with arena based allocator that burden the project with all the problems of GC and none of the benefits.
GC works for operating systems, they work for hard real time systems, they work for mostly everything except severely constrained embedded systems.
> And the amount of complexity in the language just to avoid that is truly staggering.
In terms of day-to-day coding this isn't my experience. Once in a while I have tricky ownership problems to resolve, but most of the time I get by just fine without thinking much about the ownership model.
In exchange we don't have to think at all about GC tuning or object recycling, we get RAII, we get to use affine types to encode typestates, and we get easy parallelism. I'm happy about this trade.
As you can see when I started this thread I am far more concerned about build times than I am about the cognitive overhead of ownership and lifetimes.
Maybe I'm unusual in some way, but I do not find Rust hard to use once you've learned the language. You say the complexity to avoid a GC is staggering, but it seems straightforward to me. You have to appease the borrow checker, and you need to learn about some tools like Rc, Arc, Cell, etc., that provide interior mutability. Other than that, the language has been an absolute pleasure and dream to use.
I tend to write Rust the way I write Haskell, not the way I write C++. I start by sketching out all the types that I need to model the problem space at hand. This can be done almost 1:1 with Haskell in many cases. Then I start filling in the implementation, getting me from "input" types to "output" types and only very rarely running into any kind of issue with the borrow checker. Of course, instead of using immutable data structures (as is common in Haskell), I use mutable ones in Rust. The compiler guides me the entire way, and often it feels like an entire program writes itself.
As for GCs, I almost never want one. Performance matters in almost everything I write these days, and faster is always better. Rust is so easy to write once you learn it that I see no reason to accept a GC in 2020 and beyond for any software where performance matters. I do not write software for severely constrained embedded systems. I mostly write real-time backend services that process data or handle large numbers of clients. I could tolerate a GC in much of this, but there's no reason to in a world where Rust exists, and everything is faster, more responsive, and considerably easier to reason about as a result. A few years ago, I would've used a mixture of C++ and Go. Now, I'd just use Rust for all of it.
Those people would be wrong. As an extreme example: GPU programming, where GC is essentially impossible due to the architecture.
I found that translating OCaml code to Rust is frustrating, because you cannot easily and cheaply replicate the functional approach. It's much more Rustic to take an object by mutable reference and modify it in-situ than it is to take an immutable reference and return a new object. The reason is that in OCaml, you have structural sharing, i.e., multiple pointers pointing into the same data structure, which is a big no-no in Rust, so if you want to replicate the functional OCaml code, you begin allocating a new, complete data structure every time, and that's costly.
[0]: https://donsbot.wordpress.com/2020/07/04/back-to-old-tricks-...
"Rust is so clearly a byproduct of the C++ world"?
Furthermore, in which way is Rust defective to the point that it should be seen as a prototype that should be thrown away?
mbbeddr seems really nice and interesting but it is not just a language. It is a set of integrated tools around one.
Rust shares goals with C++, i.e. it wants to be a high-performance and systems language like C++, but I find the differences to be quite substantial and worthwhile.