6 ms·
First let me say: I like Rust. I'm a fan. But... it did make some early decisions that are going to be hard to shake off, most notably around build times. This
by cletus 5y ago
First let me say: I like Rust. I'm a fan. But... it did make some early decisions that are going to be hard to shake off, most notably around build times. This [1] is well worth a read.
[1]: https://pingcap.com/blog/rust-compilation-model-calamity https://pingcap.com/blog/rust-compilation-model-calamity
- capableweb 5y agoYeah, the build times. How does a normal Rust developers development environment look like? Do you have to rebuild after each change if you want to try out the change itself, after you've written tests and so on? How is the REPL experience if there is one? My only experience with Rust so far has been trying to learn it by writing applications in it and also use 3rd party CLIs, but quickly loosing interest because the "change <> try out change" cycle has been too slow and cumbersome, and installing/compiling dependencies take fucking forever, even on a i9-9900K.
- nessex 5y agoWhen I use rust, I find compile times faster and more manageable than other languages due to the speed of iterative compiles. Compiling from scratch is very slow, but iterative compiles are faster than most of my golang compiles and faster than running a JS builder in most projects. To make it extra fast, I follow the instructions from the bevy game engine[1]. With that setup, the feedback loop is quick. [1] https://bevyengine.org/learn/book/getting-started/setup/#enable-fast-compiles-optional https://bevyengine.org/learn/book/getting-started/setup/#ena...
- coder543 5y ago> iterative compiles are faster than most of my golang compiles Maybe you're comparing apples to oranges here. I've worked professionally with both Rust and Go for years now on a variety of real world projects, and I've never seen a similarly-sized Go codebase that compiles slower than a Rust one. If you're comparing incremental Rust compilation to first-time Go compilation, maybe they could be competitive, but... Rust is incredibly slow at compilation, even incremental compilation. Yes, using lld can speed up Rust compilation because a lot of the time is often spent in the linker stage, but... that's not enough to make it as fast as Go. YMMV, of course, but... my anecdotal experience would consider it disingenuous to say that Rust compile times are an advantage compared to Go, and I'm skeptical that Rust compile times are even an advantage compared to the notoriously slow webpack environments. Rust is good at many things, but compilation speed is not one of them. Not even close, sadly. "cargo check" is tolerable most of the time, but since you can't run your tests that way, that's not actually compilation.
- nessex 5y agoPossibly, when working with big codebases I'm typically working on Kubernetes controllers in both Golang and Rust. That makes for extra slow golang compiles, and the rust incremental compiles are significantly quicker in comparison. Otherwise the codebases tend to be quite small, and for those golang full compiles (the only option?) and rust incremental compiles are similarly nearly instant. It is absolutely apples to oranges, but if you just care about the everyday local workflow and ability to iterate and test, it's close enough most of the time to not be much of a problem in either case. I'm sure this experience isn't guaranteed for all codebases, and it certainly helps that I make heavy use of crates, which would minimize the work required during incremental compilation. Though I'm not actively going out of my way to optimize for incremental compilation really, beyond the config linked above.
- coder543 5y agoKubernetes is, unfortunately, not typical Go code. It uses a Makefile, which is never encouraged in Go, and it has a bunch of custom build scripts managed by that Makefile. I was looking at the Kubernetes issue tracker for other reasons, and came across one ticket open right now that mentions "fix excessive `go list` use in build scripts causing extremely long build times", so they know their build times are awful compared to what they should be. They don't even use Go Modules in the main Kubernetes code base, relying instead on $GOPATH which has been soft deprecated for years now, and hard deprecated possibly by the end of this year. Plus, Kubernetes is sitting at 5 million lines of Go code, by my count. Try compiling a 5 million LoC Rust code base... I won't wait around. I would assume that a controller written in Rust bypasses all the complex legacy of the Kubernetes code base, and that's why it can compile faster. If someone made a similar project in Go[0] to write Kubernetes controllers in Go without depending on the mega-Kubernetes code base, I'm sure it would be incredibly faster at compiling than the Rust version. Beyond that, I've heard that the Kubernetes codebase is internally just a nightmare of basically untyped `interface{}` stuff floating around everywhere, which would make the development experience subpar. I don't know how much this is exposed to custom controllers. So, if Kubernetes is your only experience with Go... I'm sorry you've had to experience that. It's a product that people seem to agree is functional and works most of the time, but I can't remember hearing any positive experience from people working on it. From what I understand, it was originally prototyped in Java, and then hastily rewritten into Go before public release, and I'm sure that didn't help things. [0]: conceptually, maybe something like this? https://github.com/ericchiang/k8s https://github.com/ericchiang/k8s or an updated fork of it like this: https://github.com/karlmutch/k8s https://github.com/karlmutch/k8s No idea how well either works, if at all.
- brundolf 5y agoIt caches things between builds (dependencies in particular only have to be built once), and if you use dev builds (the default) it doesn't take as long as production. For ergonomics you can also install cargo-watch (https://crates.io/crates/cargo-watch https://crates.io/crates/cargo-watch), which helps a bit. An important thing though, if you aren't doing this already, is to not wait for a full build to know if your types check out. You can use cargo-check if you prefer (https://doc.rust-lang.org/cargo/commands/cargo-check.html https://doc.rust-lang.org/cargo/commands/cargo-check.html), but really I recommend using an editor with immediate feedback if at all possible. rust-analyzer (an LSP) is one of the best, and should be available even if you're on Vim or something. Using Rust without snappy editor hints is fairly miserable because of how interactive the error feedback loop tends to be. If you don't rely on a full build for errors - just for actual testing - I find the build times to be perfectly livable (at least in the smallish projects I've done).
- bfrog 5y agoClean compiles do take a moment. Comparable to heavily templated C++ in my experience. On the other hand iterative development with rust analyzer going and all the dependencies already built is pretty painless. By the time you run your tests or program, it's likely to take only a few seconds to build. That said you can write terribly long to compile rust. Usually there's some trades you can make to weigh compile time as more important than flexibility or static code paths. I've written a sizeable ad server in rust with maybe 25kloc. Where I was the sole developer and sys ops person, it cost me a little upfront time but saved me many more hours in operations work.
- capableweb 5y agoI guess by in general a "dynamic programming languages" fan, "only a few seconds to build" already sounds like a lot. Different tradeoffs I guess, but hard to justify when you're used to ms compile time.
- hctaw 5y ago> How is the REPL experience if there is one? About on par with C/C++ and Go. In that you don't have one and don't want for one. REPL driven development is difficult with languages like Rust, both to implement and use. I think there are some projects floating around out there, but I personally don't see a purpose for one. It's not python or matlab.
- zozbot234 5y agoThe latest TWIR development summary mentions evcxr, a notebook-based environment for Rust that's currently being worked on, link https://blog.abor.dev/p/evcxr https://blog.abor.dev/p/evcxr Notebooks work better than raw REPL's for a language that's so heavily based on static typing, but they're idiomatically quite similar.
- capableweb 5y ago> I think there are some projects floating around out there, but I personally don't see a purpose for one. It's not python or matlab I was thinking of a REPL in the sense of common Clojure usage (https://vvvvalvalval.github.io/posts/what-makes-a-good-repl.html https://vvvvalvalval.github.io/posts/what-makes-a-good-repl....) not the basic "write lines into a separate program and then copy-paste it into your source code" that Python offers.
- staticassertion 5y agoI'm surprise to hear that it was so slow on a powerful machine. In my experience throwing more compute at a codebase can make compile times very, very fast, though of course only after the first run. It parallelizes pretty damn well.
- brabel 5y ago> How does a normal Rust developers development environment look like? In my experience, you write some code, the rust analyzer (which is easily embedded in an IDE like VSCode or IntelliJ - which has its own "analyzer" I think) gives you immediate feedback, so you know immediately if things compile or not (there are a few edge cases the analyzer might miss, so when you actually run "rustc" something doesn't compile, but it's pretty rare)... you then write a little test , and Rust has many ways of letting you do that (unit tests right into the same file as the code being tested, integration tests which let you use the code as if from another crate, and even doctests, which are like unit tests but embedded in the documentation of your code)... running the tests is a matter of pressing a button and waiting a few seconds (compilation + test runtime) normally, unless you change dependencies between runs as that requires downloading/compiling your code AND the dependencies, which can be very slow (dozens of seconds)... which is the same problem as with a fresh build, which will almost certainly run in the minutes because of the necessary local compilation of all dependencies... but the experience is not very different from something like Java or Kotlin IMO (but definitely a slower cycle than Go, for example).
- qznc 5y agoI'm so torn about macros. They are awesome but they make compile-time arbitrarily bad. The D compiler is roughly as fast as the Go one. However, D has macros though and that makes it very slow to compile sometimes. The alternative to macros are code generators. Works fine for bigger stuff like a parser generator but not for smaller stuff like a regex.
- willtim 5y agoIt's better to evaluate at compile time, if possible, rather than runtime. The biggest issue with macros is code bloat, but every serious general purpose language should have them.
- chubot 5y agoI think a problem is that programmers have little intuition about about the evaluation time of macros. It's possible that Zig's approach helps here -- since the metalanguage is just the language, you can take some of your intuition about performance along to compile time. And the macro language is not weirdly restricted, so you can write something you're more used to, with similar idioms. In the limit this is clear: I'm using several Python code generators C++ in https://www.oilshell.org https://www.oilshell.org, and it's easy to reason about the performance of Python. Doing the same in C++ metaprogramming would almost certainly be a lot slower. It would also give me less indication of code bloat; right now I simply count the lines of output to test whether my code generator is "reasonable". e.g. I generate ~90K lines of code now, which is reasonable, but if I had 1M or 10M lines of code, that wouldn't be. But there's not that much of a sanity check on macros (except binary size).
- pcwalton 5y agoMacros and compile-time function evaluation are different and fill different roles. Macros define new syntax, while compile-time function evaluation evaluates expressions written using the existing syntax. The corresponding Rust feature for the latter is not macros, but rather "const fn".