Could a stage 1 release compiler build a stage 2 debug compiler?


#1

A compiler built with debug assertions enabled can be immensely useful for tracking down bugs in rustc; but it takes absurdly long to build because the bootstrap process will involve building rustc itself with a debug-enabled compiler. Can this be avoided?

(note: I keep an old debug compiler around basically just for this purpose, and it wastes a decent 5% of my entire SSD’s storage capacity)


#2

This should be avoidable, but I’ve personally never considered the two to be drastically different performance wise. If we could get concrete numbers showing gains here that would be great; there’s actually an open PR that does what I believe you’re looking for (https://github.com/rust-lang/rust/pull/50426) or something similar. I’m hesitant to land it and proliferate the quantity of options available in config.toml without seeing what gains we’d actually get from it.


#3

I’ve always done this without setting optimize = true, because I was worried about the quality of backtraces in optimized code. Not having used an optimized debug build before, I’m not sure how much the other debug options help to alleviate this.

That said, there’s no doubt that setting optimize = true on a debug build significantly helps close the gap between debug and release builds in terms of both time spent and disk space used. (down to about a 30% slowdown, as seen in the data below)

One last remark: I seriously don’t understand why debug = true affects a whole bunch of (unspecified) configuration settings like it’s supposed to be some big red Easy button… and then tells you that you probably don’t want to use it.

A spattering of data

Release build:

====Config====
(all default settings)

====Time====
real    46m35.963s
user    149m52.183s
sys     1m18.954s

====Disk Space====
(forgot to record this, but IIRC it's usually around 3.5G total)

Debug build with optimize = true:

====Config====
debug = true
optimize = true          # (note: usually disabled by debug)
debug-assertions = true  # (note: enabled anyways by debug, just being explicit)
debuginfo = true         # (note: enabled anyways by debug, just being explicit)
debuginfo-lines = true   # (ummm... I think I just arbitrarily set this because
                            it's in the vicinity of the others)

====Time====
real    59m17.057s
user    193m37.208s
sys     1m52.945s

====Disk Space====
Largest subdirectories:
  190M    stage2-tools
  308M    stage1-rustc
  536M    stage0
  676M    stage1
  841M    stage0-rustc
  895M    llvm

Total:  6.9G

debug = true, unoptimized

Haven’t done this recently (need a large block of time), but from what I remember, the time is somewhere in the ballpark of 2-6 hours, and the total filesize exceeds 13G. (it looks like at some point I did an rm -rf stage0* stage1* on my saved copy, which trimmed it down to 3.3G).


#4

Thanks!

Looks like the difference is about ~13 minutes of wall clock time between optimized/debug and just optimized builds. It looks like it may be beneficial to get something landed which will allow us to experiment with turning debuginfo off for the initial stage0 compilation, though it’ll have to be behind some config flag…

My understanding is that most people who work on the compiler itself prefer to have debuginfo enabled in that compiler because they use it to compile test cases and want the additional checks and ability to set RUST_LOG=debug. Standard library developers generally speaking shouldn’t be compiling the compiler. So I’d expect them to also not encounter the need for a full build as you’ve described.

I guess my point here is that it seems like while this is potentially useful, it seems unlikely to be useful for more than a subset of users – and I’m not entirely sure what the use case there would be. The only thing I can think of off the top of my head is working on proc macro integration code, but that’s a relatively rare thing to do. Could you expand on why you do this?

My understanding is that the expected thing to do is optimize=true, debug=true for people working on the compiler. I don’t know of a good use case for non-optimized compiler builds (beyond maybe something like using GDB, but even then I’d expect debuginfo to be sufficient for most cases?).


So, to summarize, I think that implementing what you want is reasonable, but I’d probably say it’s P-low at this point. However, I’d be happy to put up mentoring if you’d like to work on it, or maybe you can help push @DiamondLovesYou’s work over the line.


#5

There were two times I’ve used a debug compiler, one of which definitely required stage 2 (an ICE during compiler plugin use), and the other I can’t remember (it might not have been necessary that time… or maybe the reproduction case depended on serde).