rustcompiler-optimizationrust-cargobevy

Why does this bevy project take so long to compile and launch?


I started following this tutorial on how to make a game in bevy. The code compiles fine, but it's still pretty slow (I'm honestly not sure if that's normal, it takes around 8 seconds), but when I launch the game, the window goes white (Not Responding) for a few seconds (about the same amount of time as the compile time, maybe a tiny bit less) before properly loading.
Here's my Cargo.toml:

[package]
name = "rustship"
version = "0.1.0"
edition = "2021"

[dependencies]
bevy = "0.8.1"

# Enable a small amount of optimization in debug mode
[profile.dev]
opt-level = 1

# Enable high optimizations for dependencies (incl. Bevy), but not for our code:
[profile.dev.package."*"]
opt-level = 3

[workspace]
resolver = "2"

I tried it with and without the workspace resolver. My rustup toolchain is nightly-x86_64-pc-windows-gnu and I'm using rust-lld to link the program:

[target.nightly-x86_64-pc-windows-gnu]
linker = "rust-lld.exe"
rustflags = ["-Zshare-generics=n"]

According to the official bevy setup guide it should be faster this way. I tried it with rust-lld and without, but it doesn't seem to change anything.
Here's the output of cargo run (with A_NUMBER being a 4-digit number):

AdapterInfo { name: "NVIDIA GeForce RTX 3090", vendor: A_NUMBER, device: A_NUMBER, device_type: DiscreteGpu, backend: Vulkan }

Any ideas on how I can maybe improve the compile time and make the window load directly? My game isn't heavy at all. For now, I'm just loading a sprite. The guy in the tutorial uses MacOS and it seems to be pretty fast for him.


Solution

  • The Fix

    Make sure to enable the "dynamic_linking" feature for Bevy when you want the fastest compile times. It builds Bevy as a system library (E.g. .dll file for Windows) and links your game to that library instead of building Bevy into your app, which saves a lot of compile time. This isn't recommended for release builds though as you would have to distribute that dll with your app and Bevy isn't really setup for that.

    Setup

    To enable the feature, I recommend adding the feature whenever you run your project through cargo.

    cargo run --features "bevy/dynamic_linking"
    

    This is better than adding the feature to your cargo.toml because you don't have to change your cargo.toml every time you want to make a release build. Usually you can just add the `--features "bevy/dynamic_linking" to your IDE's run configuration.

    You will need to use at least version 0.9.1 of Bevy. Note that in version 0.10 the feature was renamed from dynamic to dynamic_linking.

    Important!: These lines are necessary in your cargo.toml when using the dynamic_linking feature on Windows:

    # Enable a small amount of optimization in debug mode
    [profile.dev]
    opt-level = 1
    
    # Enable high optimizations for dependencies (incl. Bevy), but not for our code:
    [profile.dev.package."*"]
    opt-level = 3
    

    Clion / Jetbrains Specific Instructions

    Edit your run configuration at the top right of Clion and add --features bevy/dynamic_linking to the command. clion run configuration dialog showing run --features bevy/dynamic_linking in the "command" field

    Important!: You will also want to add this to the "External Linters" additional arguments under settings so it doesn't build without it and cause full rebuilds because of compiling with different features:

    Settings dialog showing the page under Languages & Frameworks/Rust/External Linters with the "Additional arguments" field set to --features bevy/dynamic_linking

    VS Code Specific Instructions

    Disclaimer: I don't use VS Code. Suggested edits are welcome!

    In your launch.json file, any place you see "cargo" add "--features=bevy/dynamic_linking" to the "args".

    json fragment showing "--features=bevy/dynamic_linking" added to the "args" section of "cargo"

    Why this didn't used to work on Windows but now does

    The two issues regarding the dynamic feature on Windows have now been resolved and I've been able to use it on Windows since version 0.9.1.

    https://github.com/bevyengine/bevy/issues/2921#issuecomment-1315886660 https://github.com/bevyengine/bevy/issues/1110#issuecomment-1312926923

    I re-wrote the GilRs backend for Windows specifically to make this work lol. (GilRs is used by Bevy and the xInput lib it linked had issues with dynamic linking)

    I just commented on the related issue for the Bevy website regarding updating the instructions.

    Update 2024: Bad news

    Bevy has gotten larger now so now even with these changes you can easily go over the Windows symbols limit for DLLs. See updated comment here: https://github.com/bevyengine/bevy/issues/1110#issuecomment-2286835295 You can try disabling Bevy features or using just the specific crates, but honestly, just use Linux/MacOS or don't use Rust. Windows is so slow compiling Rust in comparison and none of the fixes (like mold linker) work on Windows. I'm as annoyed as you are about this.