cargo icon indicating copy to clipboard operation
cargo copied to clipboard

Add more optimizations to the release build profile.

Open just-a-mango opened this issue 1 year ago • 12 comments

Problem

The release profile is used when wanting to build an optimized binary. Thus, I think it would be logical to optimize it to the fullest, sometimes at the cost of a greater build time, but I think it is a good compromise for many people, including me.

Proposed Solution

More optimizations flags should be added to the release build profile, notably lto=true and codegen-units=1, as well as optimizing all the packages with opt-level=3. This greatly enhances runtime performance, although yes, at the cost of a bigger binary size and longer build time.

Notes

I have tested what I am proposing, with the following added in my cargo.toml:

[profile.release]
lto = true
codegen-units = 1

[profile.release.package."*"]
opt-level = 3

This improved the output binary's runtime performance by orders of magnitude, thus this issue.

just-a-mango avatar Oct 27 '22 13:10 just-a-mango

I suspect lto = "thin" is a sufficient compromise that it'd be worth being the default compared to "fat" / true.

epage avatar Oct 27 '22 14:10 epage

Compile times are a sensitive area and increasing them in any way is always a worry.

I ran a test on my machine (M1 Max chip 32GB ram) against a private project that has 395 dependencies (many are very heavy) and the jump in compile time is large for "fat" LTO. The results also appear to agree that lto = "thin" could work.

One thing to consider is if changing the release profile could be breaking in some unintended way. Crater might need to be run to see if it changes anything. Either way, it might be a good idea to add a new profile that contains these changes, instead of changing release.

Test Results
profile time
"fat" LTO codegen=1 2m 30s
"fat" 2m 27s
"thin" LTO codegen=1 1m 44s
"thin" 1m 08s
No LTO codegen=1 1m 39s
release 1m 09s
"fat" codegen=1
[profile.production]
inherits = "release"
lto = true
codegen-units = 1
opt-level = 3
"fat"
[profile.production]
inherits = "release"
lto = true
opt-level = 3
"thin" codegen=1
[profile.production]
inherits = "release"
lto = "thin"
codegen-units = 1
opt-level = 3
"thin"
[profile.production]
inherits = "release"
lto = "thin"
opt-level = 3
No LTO codegen=1
[profile.production]
inherits = "release"
codegen-units = 1
opt-level = 3

Muscraft avatar Oct 27 '22 15:10 Muscraft

I completely agree with you, lto is, whatever the value, a great performance increase

just-a-mango avatar Oct 27 '22 17:10 just-a-mango

Either way, it might be a good idea to add a new profile that contains these changes, instead of changing release.

That's what I thought at first, adding a "production" profile that would optimize the binary to the maximum and which would use the flags I mentioned in the issue.

just-a-mango avatar Oct 27 '22 17:10 just-a-mango

adding a "production" profile that would optimize the binary to the maximum

Just want to make it clear. Are we proposing a new built-in profile here?

weihanglo avatar Oct 30 '22 14:10 weihanglo

One thing to consider is if changing the release profile could be breaking in some unintended way.

Currently ThinLTO creates issues with at least one common target while linking with lld; a potential fix was opened recently https://github.com/rust-lang/rust/pull/103353

memoryruins avatar Nov 02 '22 03:11 memoryruins

Just want to make it clear. Are we proposing a new built-in profile here?

It depends on what the majority of devs think. It could be a new built-in profile or it could simply be en enhancement to the current release build profile.

just-a-mango avatar Nov 02 '22 23:11 just-a-mango

I don't think the release profile should be made to optimize harder, because Rust's build times are already slow, and a full LTO can be extremely slow and memory-hungry (I have some projects that I can't build with fat LTO at all because they run out of memory).

It may be difficult to get everyone agree on what is desired for some "dist"/"production" profile. For example, I care about small executable sizes more than backtraces, so my preferred dist profiles include panic=abort, strip, and even panic_immediate_abort and -Zlocation-detail=none where possible.

kornelski avatar Feb 17 '24 11:02 kornelski

Agreeing on a dist profile would be near impossible, yeah. I think that a better way would be to add some guidance/templates/profile wizard to cargo, which would help users build the desired profile interactively, with some predefined presets.

Kobzol avatar Feb 17 '24 11:02 Kobzol

Each option for a build configuration has pros and cons, depending on the needs of the developer. But I do need some predefined templates or configurations to make the build accomplish certain goals, such as faster builds, smaller binaries. It would be nice to have written guidance from an official. It is also acceptable if there are unofficial plug-ins that implement predefined templates out of the box

linyihai avatar Feb 21 '24 07:02 linyihai

Created a Cargo subcommand for configuring Cargo projects (focused on performance aspects of configuration), might be useful to automate the creation of optimized Cargo profiles: https://github.com/Kobzol/cargo-wizard.

Kobzol avatar Mar 10 '24 15:03 Kobzol

I agree that making everyone agree on one new profile is impossible. I think it should then be considered to possibly add multiple new build profiles, each fulfilling a goal, or at least mention new ones in the docs, offering the developers the possibility to modify their 'release' profile to maximize(or minimize) a certain aspect. For example, I think there could be at least two new ones: 'performance' (or 'speed'), and 'size' (or 'binary-size'). The first one would have the modifications pointed out in my first comment, and the second one would modify parameters to minimize the final binary size. This would then allow developers to overwrite certain parameters in those profiles as they please while having a build profile aimed towards a certain aspect, as pointed out here by @kornelski :

my preferred dist profiles include panic=abort, strip, and even panic_immediate_abort and -Zlocation-detail=none where possible.

just-a-mango avatar Apr 11 '24 14:04 just-a-mango