Hacker News new | comments | show | ask | jobs | submit login

"For our 2400 loc it takes 20s for a dev build and 70s for a release build. "

I have played with rust, but not written any large amounts of code. This makes me a bit sad though, I have 7000 lines of go which takes less than a second. I think there is a bunch of bloat in software compilation which the plan9/Go people were wise to stamp out.

Compare gcc/clang/rustc build times from source with building go 1.5 from source which bootstraps itself. It comes down to something like 20 minutes vs 20 seconds.




The advantage, of course, is that LLVM has probably over a hundred man-years of optimizations in it, including two IRs (SSA LLVM IR, SelectionDAG), tons of target-specific optimizations (ScheduleDAG, Machine-level optimizations), great tooling (e.g. DWARF support, Address/Thread Sanitizer), and lots of community support. None of it is bloat as far as Rust is concerned. I optimize bare-metal Rust code nearly every day and if I had to spend time fixing suboptimal codegen due to missing optimization passes in the compiler I'd never get my job done. Especially since I work on ARM, where bad codegen punishes you hard.

There's certainly a lot of room for improvement in Rust's build times, but LLVM was completely indispensable for the language to get off the ground, and I don't regret using it for a minute.


What would benchmarking say the slowest part of rustc is? Typechecking/semantic analysis, llvm, or something else.

LLVM is a great innovation when it comes to making new languages from scratch, High performance will hopefully be one of rusts strong points, so its good to have so many companies working on llvm performance for free.


On debug builds, it's about evenly split between typeck/borrowck and codegen (including LLVM IR construction and LLVM passes). On release builds, LLVM optimization time tends to dominate everything.

Niko Matsakis is actively working on improving typechecking time--there should be plenty of tricks we can try once we have enough data as to the lowest-hanging fruit. Felix Klock and others are working on reducing the amount of LLVM IR we generate to speed up codegen. There have also been designs for incremental and parallel compilation that will be long-term but have potential for big improvements down the road.

I think with careful work we can get down to a good edit/compile/run experience. Compilation speed probably won't ever be as good as a direct-to-assembly compiler for language with an extremely simple type system with no real IR for optimization would be, but I don't believe there's a magic bullet that will beat LLVM's compiler performance while providing excellent optimization, and for Rust's goals we need the runtime performance.


I think a big issue is that even if it takes a few more seconds, it is still a big win compared with C and C++ builds, usually measured in hours.

But I guess it is a block for those used to programming languages with traditional interpreter implementations.

My biggest complain when trying out Rust was the C++ build times of the bootstrapping process. As for using pre-compiled Rust, I think the compile times are pretty acceptable for 1.0.


> C and C++ builds, usually measured in hours. Do you have a source or a story about this? I hadn't heard numbers like that before.


Is rustc able to run typechecking without doing codegen?


`rustc .... -Z no-trans`. kibwen is working on a mode where rustc can generate crates with just metadata, and use it for a `cargo check` mode.


The slowest part is LLVM. (You can pass "-Z time-passes" to rustc to get detailed timing info.)

This isn't just an "LLVM is slow" problem, though. It's also a "rustc generates extremely verbose LLVM IR" problem. Optimizing the IR before it gets to LLVM is part of the plan for solving it.


It's also a "let's rebuild everything every time" problem. Hopefully, that will be fixed with support for building incrementally.

(Also note that compiling a C++ file with 2000 lines can take a very long time too)


You must not forget that thanks to the preprocessor, what looks like 2000 lines may in fact be around 200k lines

E.g. I have a very innocent 2000-line MainWindow.cpp that weighs 244419 lines when measured with gcc -E -o - | wc -l


Good point, it really is quite staggering what a C++ compiler has to digest to compile a standard "Hello, World!". Hopefully the much-anticipated module system will help here. Generally I find that avoiding Boost libraries (including std::regex) helps enormously ;)


> What would benchmarking say the slowest part of rustc is? Typechecking/semantic analysis, llvm, or something else.

I feel like there are some projects out there that trigger things with bad runtime complexities in Rust. I had to stop using the piston image library because compiling it takes 15 seconds every time, which I'm not in for.

Compiling racer currently needs 2GB of RAM for no good reason.

So I'm pretty sure there is ample room for optimizations.


If I remember properly, when Go was first developed, compilation time was one of the primary metric that Rob Pike et al were optimizing for, and drove major aspects of its design. It shouldn't be surprising that Go blows other systems out of the water in this regard.

Here he is talking about it:

https://www.youtube.com/watch?v=rKnDgT73v8s#t=8m53


My point is that you pay a price for this: LLVM's optimization passes are much, much more sophisticated than those of the Plan 9 toolchain. In optimized builds of Rust, the LLVM optimization and compilation time tends to dominate, so having a simpler type system wouldn't really help.

You could have a more C-like language that isn't so dependent on expensive optimization passes like multi-level inlining and SROA, granted, but I think most any high-level language—i.e. one that isn't a bare-metal language like C and Pascal—is going to have lots of opportunity for expensive optimizations.


If optimization is the problem, then compilation at Go speed should be possible with -O0.


Just having the ability to perform such optimizations requires an architecture that is sure to have some overhead no matter which optimizations, if any, are actually executed.


Rust could still have a toolchain like DMD devoted to fast compilation with minimal optimization. It just doesn't, yet (and likely won't for quite some time, since the present advantages of having a single toolchain are fairly significant and Rust doesn't have a formal specification yet).


There are C compilers out there that work like this (like, say, the Plan 9 C compiler) and they rarely ever get used in practice, because GCC and clang -O0 are fast enough. I think making a second compiler backend just to eliminate the IR generation step isn't going to be the solution we want in the long run.


I think they are only fast enough because developers have not been exposed to better. In general, I would like to see more aggressive build modes for CI servers, and less aggressive modes for dev.


Also, I'm confused by the word "aggressive" here. Could you elaborate please?


Aggressive optimization. I just mean on a build server time isn't as much of a factor as local development.


Multirust makes working with multiple toolchains on *NIX pretty great, but no formal spec can be a pain. Ruby doesn't have a spec, yet has multiple implementations, so it's not the _end_ of the world...


> It shouldn't be surprising that Go blows other systems out of the water in this regard.

For any developer that never used Turbo Pascal, Modula-2, Oberon compilers, just to cite a few examples among many possible ones.

Those that did, can not comprehend why companies invested in languages like C and C++, which created this notion all compilers should be slow.


Oh yes, Turbo Pascal (and even Delphi / Object Pascal) had a really fast compiler. Sigh... those were the days...


C++ isn't so bad either. 2400 loc is a really dinky program; we have a 10,000 loc C++11 program which takes 10s for a full rebuild; typical rebuild times are about a second. I don't know how rust handles incremental rebuilds, but that kind of build time feels excessive.


Other comments have mentioned LLVM (and its optimization passes) as a reson for slow compile times; just for comparison, using LDC (the D compiler with LLVM backend) on an older computer (1.6 Ghz Athlon 2650e, 2G ram, spinning rust), for a release build at -O2, it takes about 35 seconds for 10,000 sloc


> I think there is a bunch of bloat in software compilation which the plan9/Go people were wise to stamp out.

Be more specific.


linux kernel takes 20 minutes to build on my workstation, a plan9 kernel takes something tiny like 60 seconds on a raspberry pi. This is due to a few reasons.

1. Plan9 C does not allow headers to include more headers, this speeds up compilation, as there is far less useless preprocessor churn.

2. Plan9 C/Go does not do heavy optimisation, but does a decent job.

3. The system has less code overall, something like 1 million lines of code for something like gcc seems like bloat to me, They don't remove useless features and dated features as fast as they pile it on.

The whole Go compiler builds from source for me before the gcc configure script has completed.


> 2. Plan9 C/Go does not do heavy optimisation, but does a decent job.

That's not good enough for Rust.

> 3. The system has less code overall, something like 1 million lines of code for something like gcc seems like bloat to me, They don't remove useless features and dated features as fast as they pile it on.

Those GCC optimizations matter. You simply cannot get away with competitive performance with an AST-to-assembly plus peephole optimizations on the assembly anymore. SROA, SCCP, loop invariant code motion, algebraic identities, vectorization, aggressive alias analysis, etc. are all very important.


Imo compilers should only optimize specific functions which are known to be a code hotspot.


That will result in very poorly-performing code. I liked DannyBee's quote (paraphrased): "Most applications have flat profiles. They have flat profiles because people have spent a lot of time optimizing them."


There are times squeezing every last bit of performance is great. I am saying is in general there is no need to run -O3 on a 500 line function which is run once at initialization compared to a compute kernel. Our compilers and languages don't have the granularity to specify this currently.

I do want more specialized optimization tools however. Things like automatic super optimizers [1] which can be targeted by programmers with special directives.

[1] http://theory.stanford.edu/~sbansal/superoptimizer.html


According to a quick google search, both gcc, clang and msvc allow turning off/on optimizations at a function level, via #pragma/attributes?


interesting!


Well in that case... if you consider optimizing non-hotspots as "bloat"(?) then you are coming at this from a whole other viewpoint than most of us who have embraced optimizing compilers. :-)


1) seems like a language fault and not a compiler fault.

2) heavy optimisation is not "bloat".

3) "seems like bloat" is a too vague argument. Fine enough point about them supposedly not removing useless features.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: