I am interested in how you got that impression, because at least in our official surveys, it's often one of the most-requested improvements to Rust, and it's something that we're constantly working on improving. Still a ton of work to do though!
For what it's worth, my workflow is closer to yours than "compile twice a day." And if you're using rust-analyzer, by default, it compiles the code every save!
I love rust-analyzer! But I'm not sure what you mean by "it compiles the code every save." I love how fast it can type-check my code, but I was unaware it could actually compile my code into something I can run? I thought it was just a LSP provider.
Before we get into that, to answer the other question:
> But I'm not sure what you mean by "it compiles the code every save."
Rust-analyzer (by default) will run "cargo check" on save. cargo check does everything except codegen, so it won't give you something you can run, but it does invoke the full set of compiler analyses and everything else.
Now, what it does with the type-check stuff is the key to understanding what you're missing from the compiler team roadmap, funny enough. So rust-analyzer is actually going to end up merging with the rustc codebase eventually, if all things go to plan. Basically, rust-analyzer is slowly re-implementing the compiler from the outside in. It's doing this because the best way to get the largest win on compile times is to completely re-architect the compiler. This comment is too long, so I won't get into too many details, other than to say that it's going to be less like the Dragon Book and more like C#'s Roslyn, if that means anything to you.
It's doing this by taking advantage of a process called "librarification," which is extracting stuff from the compiler into re-usable libraries. You can see this on the notes when they talk about chalk; chalk is the next-generation trait resolution system. This is integrated into rust-analyzer, and into the compiler. So slowly, bit by bit, things are being re-architected and integrated in a way that will be much, much better in the future.
So this is a massive, massive project that touches everything, and so there's nothing spelled out in the minutes that says "this is for compile times" because the folks involved already have this context, basically.
And so yeah, that's the big project. There are also contributors who, while this larger work is going on, are working on individual PRs to make things faster. See https://blog.mozilla.org/nnethercote/ for one of the largest contributors in this regard, that talks about the work he's doing. But that doesn't appear on this either; there's no need for a plan or coordination here.
... does that all make sense? I am thinking maybe it would be good for us (to be clear, I mean the Rust project, I am not on the compiler team and am not doing this work) to like, actually write a blog post on all of this...
If rust-analyzer will eventually introduce those gains to rustc, that is fantastic news, and I'll be watching it with great interest! The improvement from RLS to rust-analyzer is exactly the type of improvement that brought Rust from the "fascinating tech demo" to "I could actually see myself using this day-to-day."
And yeah, I'd love to read a blog that went into more detail.
> working on individual PRs to make things faster. See https://blog.mozilla.org/nnethercote/ for one of the largest contributors in this regard
Yeah, I read through that too. He's my hero! :-) But the feeling I got when reading it was: "fast compile times" really need to be part of the DNA of a language. Let me explain what I mean. Some languages, like Go and TypeScript, have this in their DNA, and that means that every design decision and every addition to the language is considered seriously through the lens of compile time speed, and vetoed if it were too costly. But with Rust, the fact that there's one guy writing a blog post about some incremental wins he managed to chalk up just... doesn't seem like it's part of the DNA. If it is, why is it just one guy, and why do a lot of his changes seem more like incremental wins than the big sweeping changes I'd expect to be necessary? I could definitely be wrong here (sounds like I am and rust-analyzer is that big sweeping change).
Thanks for all your great responses, by the way. I really appreciate it!
Any time. :D
A couple more brief comments:
> rust-analyzer seems to me to be a LSP
Remember that LSP is a protocol, something/someone has to actually figure out the answers. Like, the LSP says "please draw the squiggles here", but something has to actually say "line 1, column 10, please". Doing that involves semantic analysis, which is what a compiler does.
> And I thought that codegen and linking was the slow part in Rust
It is the slowest part of the current architecture, but that doesn't mean that the current architecture is the best possible one.
The RLS invoked the compiler, and then examined its output to say "line 1, column 10, please". And you said you saw the improvement with the architectural switch to rust-analyzer. Same thing.
> "fast compile times" really need to be part of the DNA of a language.
You are correct that, when push comes to shove, if there's a tension between, say, runtime speed and compile-time speed, Rust will choose runtime speed. Rust will not have compile speed as high up on the list of concerns as Go does. But it is important enough that we don't let major regressions happen, and actively pursue improvements where possible. https://perf.rust-lang.org/ for example, tracks this data over time for this kind of reason.
> why do a lot of his changes seem more like incremental wins than the big sweeping changes I'd expect to be necessary?
Well, again, it's not always either or. He's doing the incremental thing, and others are doing the big sweeping changes thing. His improvements land nearly every release, but the bigger projects take a lot longer. They work in tandem to make things better than they were before.
I have therefore developed a reflex where I hit Cmd-S every time I finish typing. I actually have to put conscious effort in to stop this when using software where saving is slow.
I hear you can get this working with vim/neovim but I haven’t done it myself.
> I've often wondered how this can be possible, given that to me it's such an obvious glaring issue that all the other cited problems are distant distant seconds at best.
It's amazing how little I understand your point of view. And I'm being genuine and not critical of you at all.
To me, all of the features of the language, from move semantics, to ergonomic sum types, to nicer error handling (to me. I know it's debatable), and great runtime performance are so important, and bring me so much more peace and joy while working that compile times are literally not even on my radar. I simply don't care if they ever get better (assuming that effort is being put elsewhere. I guess if the language is "done" then work on the compile times is appreciated).
And I've certainly done real work in languages that compile fast (Go, Java) and languages that don't even compile. They always made me so much less happy because of the languages themselves just not clicking with my mental model of problem solving. Again, compile-run feedback loop just had nothing to do with it.
All that said, I use Rust Analyzer for code completion and it's generally fast enough. But it's still sometimes has a noticeable stall. That's not my favorite and it's kinda related to compile times.
Just really amazing how different people using the same tool have such wildly different modes of interaction and perceptions. Cool stuff. Cheers!
I think our difference is I spend a lot of time on graphics and games, where there's a lot of manual tweaking that you have to do. (Is 20px far enough? 25px? Is 1 second long enough for the explosion? Maybe 0.5s instead?) There's just no way to test it outside of rerunning the app.
Rerunning your code continually is no longer necessary in a language like Rust, because the compiler already does that for you.
People complaining about slow compile times in static languages like Rust, Haskell, Scala miss the forest from the trees, which is that the compiler eliminates entire bug categories, logic you'd otherwise need to check at runtime, either via unit tests or at least by running the code locally. Compiler times can always be better, but the compiler works as a theorem prover and the slowness is entirely justified, overall yielding a better ROI.
N.B. I'm not saying that with Rust you don't need to run your code or have unit tests. There's only so much a compiler can prove. But you no longer need to do it as often.
You can't switch to a language like Rust and expect Python and if you do, then the experience is going to be horrible, because Rust is a very different language.
No it's not. It's just preferable to do your work in smaller batches so that your feedback loop is fast and you know exactly which change broke things, rather than making 10 changes and then having to figure out which of those changes 4 bugs relate to. And it's better to discover a flaw in your implementation early rather than late, which is also easier when working in small increments.
Getting feedback quickly can be useful (especially when trying something new), but not needing it is liberating (especially when trying something new).
The reason I hate Spring for example (not that I've worked with it extensively) is that the documentation gives you zero feel for what you expect the behaviour to be. It will compile, but until you run it and check what it's doing, very often you'll be developing with no idea of what you're actually building.
Especially if you're trying to get specific behaviour of what you want to see (e.g: figuring out why it won't send mail, or why it doesn't ignore a certain json key or whatever), it still needs many runs to get right.
The parent comment was insinuating that, when developing in Rust, one can leverage its type system to replace this trial-and-error with static verification. And, indeed, if what you're worried about is a dangling or null reference error, the Rust type system has a rich language for specifying expected behavior so you don't have to run your code to check it.
If, on the other hand, your job description includes the nebulous mandate to "make it look right," there isn't any feasible way to design your types so that Rust can check that. For example, sometimes I have to do something like "make sure the dialog box is wide enough that it doesn't truncate the title string on any relevant platform." The Rust type system has no way for me to query several versions of macOS and Windows about when they start truncating dialog-box title strings and size my dialog that way, so here I am, still performing this task by trial-and-error, waiting forever to compile my code each time.
Nothing about this is Rust-specific by the way. I'm similarly bearish on statically-verified cross-platform dialog boxen in Haskell. And that's one of my dumber "make it look right" tasks - I work on CAD software so most of them involve 3-D graphics and/or computational geometry.
And, returning to the parent comment, waiting for C++ to compile in order to test things is a giant fucking time-sink and drain on my productivity. It can't really be automated, or, if it can, it's way beyond the reach of this organization's know-how.
In summary, I call bullshit on static verification replacing snappy trial-and-error in the UI / Graphics space. In practice, you're left shifting UI / Graphics customization out of the host language and into "content" so that you can tweak it without re-compiling. But this is another massive fucking time and complexity sink that only exists because at some point you let your compile-times get so far out of control that your people couldn't do their job ("make it look right") in a reasonable amount of time.
The elegance is free.
Type checking and Parsing isn't bottleneck in Rust compilation. Code generation is. LLVM is particularly heavy and while it generates optimized code, it is quite slow.
Go Authors didn't pick LLVM because of compile speed reasons (as well as complexity), and that turned out to be worthwhile tradeoff.
Anyway in C++ land massive compile times are just as much of a problem. Fast code is expensive. Go’s a lot of things, but being good at generating fast code ain’t one of them (looking holistically anyway).
Indeed, because all bigtech can invest on is LLVM and C++.
The research on compilers and optimizations has not been getting the attention because of LLVM monoculture and the monstrosity that is C++.
Even if you count the size of ode after monomorphization, I am pretty sure the Go compiler compiles it much faster. Because the compiler is not in the benchmarks rat race of adding one optimization pass from every academic paper in the world for diminishing returns. That would be unnecessary for a development compiler.
Go compiler could have an optimized slow build option, in ideal world, but that's a different matter altogether.
I much prefer working from a logical and thoughtful approach rather than iteration. At the point where I start a build I am already reasonably confident that it will do what I want it to.
There are some bugs where I will need to re-build several times consecutively but these are relatively rare for me (I work on REST API systems - so nothing too crazy).
The main thing that I use compiling for is to validate little off-by-one things. Like, is substring() exclusive on the second parameter? What about range syntax and the slice operator? What if I wrote + 1 instead of - 1 somewhere, or did < instead of <=? I could spend a few minutes combing documentation, or just compile it and check immediately. Well, assuming compilation is fast anyways.
I'm a really big fan of reading the docs (or, where the docs are insufficient, the source), and will always have docs.rs open alongside my editor. While the examples you provide are easily validated by testing (and I'd probably use `evalr` in `##rust`, or some similar thing, for them), many subtleties can exist in more complex functions, so not reading the docs/source for unfamiliar functions feels like programming-by-guessing to me.
(OK, you could read preferences from a file, but then you'd have to optimistically write every value you'd ever want to recompile to a file. I've tried this, but it's far too much overhead.)
I'd also recommend getting used to serialisation/deserialisation. Serde for Rust makes this remarkably easy. Writing every setting to a file is simple if the compiler can do it for you, rather than you walking the long way around.
Also there are also a shit-ton of minor logic-changing modifications when you're writing prototype gamedev code, (for example, moving an if statement here or there to tweak the physics of your platforming). These cannot be easily represented in config files, and this is why people attach lightweight scripting languages like Lua to their game engines (so that you don't have to wait for those atrocious C++ compile times when tweaking your gameplay code).
(Ironically, serde is known for its atrocious compile times, which really makes the situation even worse. Because of this some frustrated Rust gamedevs wrote their own serialization libraries such as nanoserde (https://github.com/not-fl3/nanoserde)... but you get the point.)
But I work on network protocols and file formats and parsers and video transformers and user interfaces (often command line or web) and a long time ago games ;P... I make a small change and then I want to see the behavior difference. I almost always type code that compiles, but that doesn't mean it did what I want when interacting over the network: rust doesn't provide anywhere near powerful enough type abstractions to actually prove my code is correct... it only is proving that my code can't crash and will avoid undefined behavior.
What is so frustrating is that there is nothing about Rust that makes it impossible to make fast. With C++ I get to manually make tradeoff in my code on a file-by-file basis with an assumption that my project will be built out of thousands of mostly-independent fragments that I am able to compile incrementally or in parallel. I can very rapidly isolate individual functions I am working on for fast iteration without having to restructure my project, I can tell the compiler to instantiate templates in different ways to reduce dependencies, and I have designed a system to let me do parallel compiles on AWS Lambda (I haven't yet gotten my build environment to be ready for a -j1000 parallel build, but I am somewhat close).
I have been integrating some rust libraries into my codebase (I haven't even gotten to the point of really coding in it omg) and Rust is just so painful and frustrating to work with... and it really does just seem to be, as you pointed out, a matter of priorities and interest: there is this myth that it is some kind of tradeoff on the type system, but it isn't; it is just that the people who work on rust seem to not work on the same kind of projects that we do, at least in the same way, and so have made a bunch of trade offs like "I would rather never have to type a prototype than save any time compiling" and "I would rather my build system never have to consider dependency management than save any time compiling" and "I would rather provide the highest possible quality resulting binary than save any time compiling" (which is at least one I can appreciate, but only once a month when you cut a release... not the hundreds of times a day that I recompile my C++).
Rust outputs prototype information in .rmeta artifacts that are generated as one of the first steps in compilation, so this is not a compile-time issue. AFAICT, dependencies are also tracked, and debug vs. release switches are provided that also control things like binary optimization.
The real "problem" for compile times in Rust is that Rust makes it idiomatic to write code that's slower to compile. That's really all there is to it. If you were to literally write Rust like it's C, you'd find that there's no real overhead introduced by Rust per se.
(This is not to say that improvement is not possible, of course. Even what's "idiomatic" can be tweaked over time to reduce the amount of excessive, duplicated work that the build system has to do. Newer features like const generics will probably make this feasible in the future, and improvements in the compile workflow itself will do the rest.)
I am quite curious how usable Rust/WinRT will turn out to be for WinUI work.
I know exactly what you mean. Front-end development can be this way, too.
I think it's OK (and probably true) to say that you shouldn't use Rust for cases like this right now.
I think that's true, but only because of the slow compile times. Which is why they're so frustrating. Rust would otherwise be an excellent language for these use-cases.
• The Azul GUI toolkit uses CSS for styling of its widgets, and hot-reloads stylesheets.
• The Mun programming language is designed for the sort of niche Lua is often used, with hot-reloading scripting-like functionality to augment your Rust code. (Well, Rust is the main host language at present, anyway.)
Rust has a testing facility that can be used for these things. By default, all "example" code that's included as part of a doc comment ends up in the test suite. And because test cases are small and self-contained, they're also very quick to compile.
I think the main reason why I dislike working with dynamically typed languages is that most of them make the reasoning of code a lot harder. If you're able to reason about the code at hand, then there's a lot less need to run the code for every small change.
Maybe it's time to switch to an interpreter ? :-)
That being said, C# is clever enough to only need to recompile the assemblies affected by your code change, so often you can get away with 10 second compile times even for large solutions.
So you had to work in individual projects at a time, slowly going through and changing stuff project by project.
VS wouldn't even build it either, really. YOu had to build via batch file that did various ms build magic. I would make changes, set of a build and go to lunch, then come back and fix the errors.
Once you checked the code into source control it would trigger a build which would sometimes take upwards of an hour :( I hated that code base.
It got even worse when they added Coded UI tests. Wait an hour for a build and then a random Coded UI test would fail and the advice from the people who wrote the Coded UI was "just run another build!", yeah, flakey tests on a code bases that tests an hour to run...
Only one of them says anything and it an empty statement like
> F#'s compile times also seem to err on the long side but not very much so, my impression goes.
However it is quite easy to validate write the same algorithm in F# and Rust and then compare.
Ah but Rust is AOT compiled, easy, use NGEN, .NET Native, or Mono AOT for the F# compile time measurements.
People should be educated on the huge bias introduced by personalized services like google.
I'd love a REPL that could somehow load the state of my entire app so I could test stuff out, but I've never found a language that could do that and also had reasonable type safety guarantees.
But god it's slow... Some static analysis support would also be hugely appreciated. Not being able to check everything doesn't meen you shouldn't attempt to check something! Many specs are type predicates anyway.
Clojure spec is great at system boundaries but it's hard to describe it is a type system, it's a predicate system it can define very arbitrary constraints mostly at runtime
I can’t imagine not looking up the documentation to do this.
If a language had a REPL I may then confirm it in the REPL, but almost certainly would pull up the docs first.
Definitely a leftover from when I was a kid, in the early 90s, without ready access to computers. I remember lying at a hospital bed and filling pages and pages with C64 programs, using pen and paper.
This kinda forced me into the paradigm of "think through invariants and structure first". To this day, typing code out on a computer (incl. compilation) is almost mechanical, not a vital part of the design process.
I don't think typed vs untyped languages really makes a huge difference if you're designing code this way. The difference comes when the compiler can actually verify your design, if you don't compile it doesn't really matter what the compiler can check.
I mostly work with C#, and occasionally I might only end up compiling the project a couple of times in a day, but I'll probably be building a test project several times in the meantime (e.g. after adding each test).
Alternatively, if I'm building a web GUI, I'll probably be building quite frequently, making sure that data is bound correctly and that the UI looks as expected.
It is easy to let a project slowly slide into a state where this workflow is no longer possible, especially in high-level languages like modern C++ or Rust, when even incremental builds take so long that it throws you out of "flow".
But anyway, I think this sort of working style doesn't have to do with a language's type system, but is a personal choice and one isn't necessarily better than the other, but certain personalities might be attracted to certain language communities, and thus directly influence priorities (e.g. a large part of the 'modern C++' community seems to think that compilation time and good runtime performance in debug builds are not high priorities, which from my point-of-view is entirely irrational).
I also use assertions and unit tests, because the type system still has its limitations (or some things would be too awkward to express), but I can move forward a long way without actually compiling a project.
So, for my workflow relatively fast compile times are mandatory.
(Altough, I really wanna get out of desktop dev.)
Confusing since this is, to my knowledge, a top 3 issue just about every year.
That said, I think Rust programmers dislike compromise (maybe to a fault). Rust is naturally a 'have your cake and eat it to' language and the community very much likes to be best-in-class, so compromises on runtime performance to improve compile time (which is one way you can go today) are often not seen as viable by a large part of the community.
For what it's worth, I think I've called out compile times as probably one of my top issues with Rust, working on a fairly large and quite dependency heavy codebase. It isn't a deal breaker for me by any means, but it's a pain.
Typically this tension would be resolved with o-level flags (O1, O2, O3...).
Sometimes, non-release builds are too slow to meaningfully run. It is not uncommon for release builds to be extremely faster than debug builds.
That being said, I'm not aware of it making any meaningful difference.
O1 vs O3 is probably a fair way to do things. Some people will do that for debug builds, to get a mix of reasonable performance (for tests) and reasonable compile times. I'm not sure how meaningful the difference is going to be between O2 and O3, it's been a long time since I'd looked into it, and back then O3 wasn't really a thing people did.
I used to be the same way, but the more I practiced holding the state in my head while I worked, the better I got at it.
> One group loves fast compile times and quickly validating hypotheses.
You just don't need it. As you make changes, the delta between expected behavior and actual behavior continues to grow. You begin to develop an intuition for what kind of things might not work as expected, and you can conceptually model around those things and continue to build your logic and make your changes.
An IDE helps immensely with type error minutiae. I'm using CLion and it's pretty great. For the few cases it can't figure out the types for you, you can run "cargo check".
I'm confident that Rust has made me a better engineer. I don't need to continually save and evaluate and I can do deeper work with more uninterrupted flow.
Give it a try! I think you'll start to acclimate.
Edit: Why the downvotes? I stated my personal experience as it relates to OP's observations. I improved in how I approach problems after exposure to Rust.
Still, I appreciate your optimism. I'll give it a shot! Especially for things that aren't graphical.
For a contrast, I don't notice compile times at all in just about any language for the most part: when you reach the "few million lines of code" size, there's no language that is going to be instant; and for embedded/systems work, committing a change can involve things like creating builds for N different architectures and running a test suite that may have to control hardware [run times of the test suite are measured in hours to days]. At this scale, anything that the compiler catches, even if it takes an hour to compile, saves an order of magnitude more time later in the process.
It's legitimately a hard problem to design a language that works well for both projects in the few tens of thousands of lines of code size -- i.e. tossing together a quick prototype -- and scales to millions of lines of code or larger.
I get that there're some differences in the games domain, but I don't quite get your examples, because changing the position or color of objects seems like a data and not a code change. If you have these properties as data you might be even able to change them on the fly, in the running game, which will increase your iteration times quite a bit more than any faster compile times.
Doesn't that partially defeat the point of having a powerful compiler? The more work the compiler does, the less we have to keep track of in our head (and conversely, much of the pain of coding in a language like Python is the amount of stuff we need to mentally keep track of).
I think this is somewhat orthogonal.
Unexpected behaviour and errors can be caught by means other than constant recompilation, and tools exists to do just that. In IDEs, these tools tend to become invisible, seamless, and can be relied upon without much configuration; for those accustomed to less integrated environments, the manual configuration required to get these tools up and running becomes a hassle.
I suppose using those tools efficiently and constant recompiling are different ways to solve the same problem, but I wouldn't say it's solely the compiler's job even in the latter case. For languages that aren't super-fast for compiling like Rust, Swift, etc. there may be much more reliance on those other tools.
There’s two sides to this: on the one hand, you don’t have to keep as much info in your head because the compiler will tell you if you ask it. On the other hand, when you do try to keep state in your head, the compiler is able to double-check that for you so that you don’t have to do it perfectly.
With a language like Python, you’re working without a safety net, so you make small, cautious, steps in order to not fall. A strongly-typed language like Rust enables you to make larger, bolder, changes in one go, confident that the little mistakes will get caught.
And if you can write program in very fast language, why not? There doesn’t have to be need. Just no reason not to
I just don't agree with statements about memory safety and speed. The thing is much more complex. I think simply stating "Use the best tool for the job" is much better than showing bad examples.
Because everybody needs memory safety and wants speed. Nobody wants to write unsafe slow programs (Well, I HOPE). Nobody wants to drops either of those requirements. When you drop those requirements, it's because of tradeoffs (I think memory safety shouldn't ever be dropped, yes use GC lang if you want to, but in 2020 memory safety should be a very hard requirement)
Once you get your cache warm, it's pretty much instant. If not, run `cargo check` instead of `cargo run`. You can also use rust-analyser for an in-editor <1s feedback loop.
That's why you should use `cargo check` instead : it will only run the rust compiler frontend, but not the LLVM linker.
It can't catch many logic bugs, eg forgetting to update a variable's value. The type system can't help without non-straightforward techniques, and at that point it is diminishing returns.
A powerful type system shouldn't be an excuse for not being able to iterate fast.
> One group loves fast compile times and quickly validating hypotheses
In Rust, it’s sufficient to type check (if it type/borrow checks, it will probably work) and Rust can type check in real time via rust-analyzer. This is much faster feedback than running your program or even its tests.
Of course, Rust’s type/borrow checker is also choosier than many others, and you still spend more time fighting with errors that don’t actually improve your code’s correctness (e.g., borrow checker errors are rarely indicative of a bug in a single-threaded context). So Rust’s iteration loop is quite fast but it’s development velocity is still relatively low (even when adjusting for quality), but it’s improving all the time.
I used to be the kind of dev who compiles every tens minutes. The thing is, on Android compilation time are just getting larger and larger. Anecdotally, this is not because the tooling team is not interested in build performances, on the contrary they continuously work on it. However they are currently losing the battle : the median app complexity is growing way faster than they are improving the build times.
I mostly got used to it. I can write code for a whole day and only compile once or twice. The more I am accustomed to our ecosystem and codebase, the less I feel the need to compile frequently.
The only exception is for graphics code. The only way to know if something looks correct and good is often to compile. For that reason, while I still love writing polished animations, I dread having to compile 10 times in a row to get it just right.
```
[target.x86_64-unknown-linux-gnu]
rustflags = [ "-C", "link-arg=-fuse-ld=lld" ]
```
`-Clinker=clang` also works. I think you need a recent `gcc` (8 or newer) for `-fuse-ld=lld`. For `linker=clang` you probably need `clang` installed.
Permalink: https://reddit.com/r/rust/comments/dsfi5m/rust_2020_are_we_c...
The latter. Validation/type checking is super quick. It might slow down a little bit if you do a lot of compile-time processing via macros, etc. IDE support is also improving a lot, and many Rust devs use an experimental component known as rust-analyzer to do the IDE-based validation you're talking about.
The project i'm working on now takes ~8s to compile. Perhaps too slow, but i guess it just doesn't bother me. Though i definitely want to see it improve for wider adoption, as it's clearly an issue for many people - I just have difficulty feeling the pain in this case, i guess.
edit: I imagine i compile once every 5 min of code writing. Varies by problem solving of course.
Interestingly, my case is the exact opposite. When I am coding in Typescript or Python I'm out of place, since I got used to first write the types to make sure everything is aligned, _and then_, start writing logic...
Even in Typescript this workflow is not easy to do, since its compiler is nowhere as powerful.
I see comments a lot about "this is too slow" but rarely are numbers provided, neither the actual times nor the expected times.
You may have something setup wrong and are seeing unusually long compile times. Or your expectations may not be realistic. Or you're just an outlier whos work triggers some pathological compile issues.
But without data, we can't know what's going on.
10 seconds is basically as slow as I'd accept. I wouldn't love it, but I'd suffer through it if I had to. But what I really didn't like was that my feeling was it wasn't the bottom - adding more deps or more lines of code looked like it would continue to increase the time without bounds.
I like doing a lot of game dev and graphical work, and it often requires really rapid iteration to test small changes. (How fast should the AI walk? Should he turn around at this point? Does this logic "feel right" like this, or do I need to trigger it conditionally?)
But if their use case is twice a day or similar it makes sense. Why care about compilation time at all if its seen as that rare?
Other opinions exist.
(I know that compilation speed is a Hard Problem, I know that I'm comparing apples to oranges, I know that Rust does fancy magic that other languages could only dream of. But everything that slow compiles buy me won't get bring me back flow state.)
One think that’s helped me stay “in the flow” is switching to rust-analyzer instead of the current official RLS. Much faster, I leave format on save turned on, so `cargo check` output is usually ready in about a quarter of a second after save.
I LOVE rust-analyzer. It's actually what got me to reconsider Rust after I tried a year or two ago, and it is SO good.
https://github.com/rust-lang/rust/issues/39915#issuecomment-...
https://doc.rust-lang.org/1.22.0/unstable-book/compiler-flag...
If installed, you can run
RUSTFLAGS="-Clink-arg=-fuse-ld=lld" cargo build --releaseI am less sure, but I would think that's expected, given that it has to link everything together into the final binary. You're gonna end up giving the linker more work to do, as you suspected.
Why compile again after adding a comment?
The most common trivial change would be to add a dbg! statement.
You can find how to install and use it here: https://github.com/mozilla/sccache
Does Rust have anything that prevents it from being run interpreted?
Well, there's a simple answer... https://xkcd.com/303/
So while adding hardware helps (up to a point), Rust is definitely an outlier when it comes to compilation speed.
That's hardly the only other AOT language competing with Rust though, and while some of them are simpler on a language level (i.e. C) the compilers do a fair share of work in the optimizing stage of those simpler languages. There's also several languages that do quite a bit of heavy lifting during compilation, like Zig and Nim have extensive compile time features for example. And Nim does two passes since it compiles to C first (by default) and then that's compiled to machine code.
On balance, I don't think you can wriggle out from the fact that Rust compiles slowly compared to its competitors.
Even the Rust team admits this and are working on improving it.
The OP sounded like they wanted to use rust except for this one issue of compilation being too slow for their development style.
How fast is fast enough and is that achievable just by throwing some money at the machine?
Perfect is the enemy of good enough as they say.
This honestly is a bad habit. Thought it does depend quite a bit on the type of work you are doing. For some things it is necessary especially if it is inherently fibbly.
Rust is a language to which the programmer must adapt his way of working and thinking. If the programmer is too set in his way, his Rust journey will be unsuccessful. If the programmer is adaptable, he will come out in the end a better programmer, because the Rust way is actually the right way.
I think I actually went a couple of weeks once before trying out my program for the first time and there was no big deal to get it to actually work in the end.
I'd like to hear some justification for this rather than a blanket assertion. Just because our work styles differ doesn't mean that my style is necessarily wrong.
> Rust is a language to which the programmer must adapt his way of working and thinking.
I mean, Rust is actively attempting to improve compile times. It's not like devs made them intentionally long to cultivate good programming habits or something. So I'm not sure how this is relevant.
I keep reading in Rust surveys that Rustaceans just don't care that much about compile times enough to prioritize improving them. I've often wondered how this can be possible, given that to me it's such an obvious glaring issue that all the other cited problems are distant distant seconds at best. I have a theory: there must be two groups of engineers. One group loves fast compile times and quickly validating hypotheses. The other group must value thinking about their code a lot more than running it, and so compile times aren't that important. My guess is that, while the second group hangs around and loves Rust, Rust has completely driven away the first group (including myself) to the degree that they don't use the language enough to even fill out the surveys.
Anyways, I know it has a wide swath of use cases, mostly in systems programming. I'm just bummed that if I ever do any of them, I won't really enjoy it. :-(
[EDIT:] Gotta go to sleep, it's far too late here. I really appreciate all the thoughtful replies. Rust's amazing community is another reason it annoys me that I can't fully get into the language as I'd like to.