diff --git a/Cargo.toml b/Cargo.toml index a2a953e7c5..3f2e6909e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1534,3 +1534,9 @@ target_sdk_version = 31 [package.metadata.android.application] icon = "@mipmap/ic_launcher" label = "Bevy Example" + +[profile.wasm-release] +inherits = "release" +opt-level = "z" +lto = "fat" +codegen-units = 1 diff --git a/examples/README.md b/examples/README.md index 504928ed68..97c7acaa0a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -459,7 +459,9 @@ following commands. ```sh cargo build --release --example lighting --target wasm32-unknown-unknown -wasm-bindgen --out-name wasm_example --out-dir examples/wasm/target --target web target/wasm32-unknown-unknown/release/examples/lighting.wasm +wasm-bindgen --out-name wasm_example \ + --out-dir examples/wasm/target \ + --target web target/wasm32-unknown-unknown/release/examples/lighting.wasm ``` The first command will build the example for the wasm target, creating a binary. Then, @@ -480,6 +482,83 @@ python3 -m http.server --directory examples/wasm ruby -run -ehttpd examples/wasm ``` +### Optimizing + +On the web, it's useful to reduce the size of the files that are distributed. +With rust, there are many ways to improve your executable sizes. +Here are some. + +#### 1. Tweak your `Cargo.toml` + +Add a new [profile](https://doc.rust-lang.org/cargo/reference/profiles.html) +to your `Cargo.toml`: + +```toml +[profile.wasm-release] +# Use release profile as default values +inherits = "release" + +# Optimize with size in mind, also try "s", sometimes it is better. +# This doesn't increase compilation times compared to -O3, great improvements +opt-level = "z" + +# Do a second optimization pass removing duplicate or unused code from dependencies. +# Slows compile times, marginal improvements +lto = "fat" + +# When building crates, optimize larger chunks at a time +# Slows compile times, marginal improvements +codegen-units = 1 +``` + +Now, when building the final executable, use the `wasm-release` profile +by replacing `--release` by `--profile wasm-release` in the cargo command. + +```sh +cargo build --profile wasm-release --example lighting --target wasm32-unknown-unknown +``` + +Make sure your final executable size is smaller, some of those optimizations +may not be worth keeping, due to compilation time increases. + +#### 2. Use `wasm-opt` from the binaryen package + +Binaryen is a set of tools for working with wasm. It has a `wasm-opt` CLI tool. + +First download the `binaryen` package, +then locate the `.wasm` file generated by `wasm-bindgen`. +It should be in the `--out-dir` you specified in the command line, +the file name should end in `_bg.wasm`. + +Then run `wasm-opt` with the `-Oz` flag. Note that `wasm-opt` is _very slow_. + +Note that `wasm-opt` optimizations might not be as effective if you +didn't apply the optimizations from the previous section. + +```sh +wasm-opt -Oz --output optimized.wasm examples/wasm/target/lighting_bg.wasm +mv optimized.wasm examples/wasm/target/lighting_bg.wasm +``` + +For a small project with a basic 3d model and two lights, +the generated file sizes are, as of Jully 2022 as following: + +|profile | wasm-opt | no wasm-opt | +|----------------------------------|----------|-------------| +|Default | 8.5M | 13.0M | +|opt-level = "z" | 6.1M | 12.7M | +|"z" + lto = "thin" | 5.9M | 12M | +|"z" + lto = "fat" | 5.1M | 9.4M | +|"z" + "thin" + codegen-units = 1 | 5.3M | 11M | +|"z" + "fat" + codegen-units = 1 | 4.8M | 8.5M | + +There are more advanced optimization options available, +check the following pages for more info: + +- +- +- + ### Loading Assets To load assets, they need to be available in the folder examples/wasm/assets. Cloning this diff --git a/examples/README.md.tpl b/examples/README.md.tpl index dff0e1506c..bfb3ebdc4f 100644 --- a/examples/README.md.tpl +++ b/examples/README.md.tpl @@ -207,7 +207,9 @@ following commands. ```sh cargo build --release --example lighting --target wasm32-unknown-unknown -wasm-bindgen --out-name wasm_example --out-dir examples/wasm/target --target web target/wasm32-unknown-unknown/release/examples/lighting.wasm +wasm-bindgen --out-name wasm_example \ + --out-dir examples/wasm/target \ + --target web target/wasm32-unknown-unknown/release/examples/lighting.wasm ``` The first command will build the example for the wasm target, creating a binary. Then, @@ -228,6 +230,83 @@ python3 -m http.server --directory examples/wasm ruby -run -ehttpd examples/wasm ``` +### Optimizing + +On the web, it's useful to reduce the size of the files that are distributed. +With rust, there are many ways to improve your executable sizes. +Here are some. + +#### 1. Tweak your `Cargo.toml` + +Add a new [profile](https://doc.rust-lang.org/cargo/reference/profiles.html) +to your `Cargo.toml`: + +```toml +[profile.wasm-release] +# Use release profile as default values +inherits = "release" + +# Optimize with size in mind, also try "s", sometimes it is better. +# This doesn't increase compilation times compared to -O3, great improvements +opt-level = "z" + +# Do a second optimization pass removing duplicate or unused code from dependencies. +# Slows compile times, marginal improvements +lto = "fat" + +# When building crates, optimize larger chunks at a time +# Slows compile times, marginal improvements +codegen-units = 1 +``` + +Now, when building the final executable, use the `wasm-release` profile +by replacing `--release` by `--profile wasm-release` in the cargo command. + +```sh +cargo build --profile wasm-release --example lighting --target wasm32-unknown-unknown +``` + +Make sure your final executable size is smaller, some of those optimizations +may not be worth keeping, due to compilation time increases. + +#### 2. Use `wasm-opt` from the binaryen package + +Binaryen is a set of tools for working with wasm. It has a `wasm-opt` CLI tool. + +First download the `binaryen` package, +then locate the `.wasm` file generated by `wasm-bindgen`. +It should be in the `--out-dir` you specified in the command line, +the file name should end in `_bg.wasm`. + +Then run `wasm-opt` with the `-Oz` flag. Note that `wasm-opt` is _very slow_. + +Note that `wasm-opt` optimizations might not be as effective if you +didn't apply the optimizations from the previous section. + +```sh +wasm-opt -Oz --output optimized.wasm examples/wasm/target/lighting_bg.wasm +mv optimized.wasm examples/wasm/target/lighting_bg.wasm +``` + +For a small project with a basic 3d model and two lights, +the generated file sizes are, as of Jully 2022 as following: + +|profile | wasm-opt | no wasm-opt | +|----------------------------------|----------|-------------| +|Default | 8.5M | 13.0M | +|opt-level = "z" | 6.1M | 12.7M | +|"z" + lto = "thin" | 5.9M | 12M | +|"z" + lto = "fat" | 5.1M | 9.4M | +|"z" + "thin" + codegen-units = 1 | 5.3M | 11M | +|"z" + "fat" + codegen-units = 1 | 4.8M | 8.5M | + +There are more advanced optimization options available, +check the following pages for more info: + +- +- +- + ### Loading Assets To load assets, they need to be available in the folder examples/wasm/assets. Cloning this