Skip to content

Commit d8463db

Browse files
authored
A guinea-pig binary for bloat checks (#332)
As per the documents inside the binary code, it is specially crafted so that all memory except the stack is reported towards the `.bss` section. For this to happen, all `rs-matter` types are allocated statically. This includes the futures (whose size is anything but trivial), which are moved/emplaced into `.bss` by the specific executor which is utilized (`embassy-executor`). TBDs: - Check why the code size reported for the riscv32imac target is more than twice as big as the thumb targets. Might just be due to the compressed size of the thumb instructions (16bit) or there could be something else going on for riscv32, as in linking to binaries we don't need and use, but not removed by the LTO - Fix the large "responder" future by splitting it into multiple tasks in an embassy-executor task pool. This should reduce these 20KB down to ~ 10KB on x64 and even less for the other targets
1 parent 12141d0 commit d8463db

13 files changed

Lines changed: 931 additions & 22 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,15 @@ jobs:
2929
toolchain: ${{ env.RUST_TOOLCHAIN }}
3030
components: rustfmt, clippy, rust-src
3131

32-
- name: Setup | Rust no-std target
32+
- name: Setup | Rust no-std Riscv32 target
3333
run: rustup target add riscv32imac-unknown-none-elf
3434

35+
- name: Setup | Rust no-std Thumbv6 target
36+
run: rustup target add thumbv6m-none-eabi
37+
38+
- name: Setup | Rust no-std Thumbv7 target
39+
run: rustup target add thumbv7em-none-eabi
40+
3541
- name: Install libdbus
3642
run: sudo apt-get install -y libdbus-1-dev
3743

.github/workflows/size-check.yml

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@ jobs:
2525
toolchain: ${{ env.RUST_TOOLCHAIN }}
2626
components: rustfmt, clippy, rust-src
2727

28-
- name: Setup | Rust no-std target
28+
- name: Setup | Rust no-std Thumbv6 target
29+
run: rustup target add thumbv6m-none-eabi
30+
31+
- name: Setup | Rust no-std Thumbv7 target
32+
run: rustup target add thumbv7em-none-eabi
33+
34+
- name: Setup | Rust no-std Riscv32 target
2935
run: rustup target add riscv32imac-unknown-none-elf
3036

3137
- name: Install libdbus
@@ -40,26 +46,69 @@ jobs:
4046
with:
4147
gh-context: ${{ toJson(github) }}
4248

49+
- name: Build | Host binary for size report
50+
run: cd bloat-check; cargo build --release
51+
52+
- name: Clippy - bloat-check
53+
if: matrix.features == '' && matrix.crypto-backend == 'rustcrypto'
54+
run: cd bloat-check; cargo clippy --no-deps -- -Dwarnings
55+
56+
- name: Clippy - bloat-check - riscv32imac
57+
if: matrix.features == '' && matrix.crypto-backend == 'rustcrypto'
58+
run: cd bloat-check; cargo clippy --no-deps --target riscv32imac-unknown-none-elf -- -Dwarnings
59+
60+
- name: Build | Thumbv6m binary for size report
61+
# run: cd bloat-check; cargo build --release --target thumbv6m-none-eabi -Zbuild-std=core,alloc,panic_abort
62+
run: cd bloat-check; cargo build --release --target thumbv6m-none-eabi
63+
64+
- name: Build | Thumbv7em binary for size report
65+
# run: cd bloat-check; cargo build --release --target thumbv7em-none-eabi -Zbuild-std=core,alloc,panic_abort
66+
run: cd bloat-check; cargo build --release --target thumbv7em-none-eabi
67+
68+
- name: Build | Riscv32imac binary for size report
69+
# run: cd bloat-check; cargo build --release --target riscv32imac-unknown-none-elf -Zbuild-std=core,alloc,panic_abort
70+
run: cd bloat-check; cargo build --release --target riscv32imac-unknown-none-elf
71+
4372
- name: Examples
44-
run: cargo build --release --no-default-features --features os,rustcrypto,log
73+
run: cargo build --release --no-default-features --features os,rustcrypto,log,zbus
4574

4675
- name: Prepare bloat report from the previous builds
4776
run: |
4877
python scripts/memory/gh_sizes.py \
49-
linux rs-matter onoff-light \
78+
rs-matter-core x86_64-unknown-linux-gnu infologs-optz-ltofat \
79+
bloat-check/target/release/bloat-check \
80+
/tmp/bloat_reports/
81+
python scripts/memory/gh_sizes.py \
82+
rs-matter-core thumbv6m-none-eabi infodefmt-optz-ltofat \
83+
bloat-check/target/thumbv6m-none-eabi/release/bloat-check \
84+
/tmp/bloat_reports/
85+
python scripts/memory/gh_sizes.py \
86+
rs-matter-core thumbv7em-none-eabi infodefmt-optz-ltofat \
87+
bloat-check/target/thumbv7em-none-eabi/release/bloat-check \
88+
/tmp/bloat_reports/
89+
python scripts/memory/gh_sizes.py \
90+
rs-matter-core riscv32imac-unknown-none-elf infodefmt-optz-ltofat \
91+
bloat-check/target/riscv32imac-unknown-none-elf/release/bloat-check \
92+
/tmp/bloat_reports/
93+
python scripts/memory/gh_sizes.py \
94+
onoff-light x86_64-unknown-linux-gnu infologs-optz-ltofat \
5095
target/release/onoff_light \
5196
/tmp/bloat_reports/
5297
python scripts/memory/gh_sizes.py \
53-
linux rs-matter dimmable_light \
98+
onoff-light-bt x86_64-unknown-linux-gnu infologs-optz-ltofat \
99+
target/release/onoff_light_bt \
100+
/tmp/bloat_reports/
101+
python scripts/memory/gh_sizes.py \
102+
dimmable-light x86_64-unknown-linux-gnu infologs-optz-ltofat \
54103
target/release/dimmable_light \
55104
/tmp/bloat_reports/
56105
python scripts/memory/gh_sizes.py \
57-
linux rs-matter speaker \
106+
speaker x86_64-unknown-linux-gnu infologs-optz-ltofat \
58107
target/release/speaker \
59108
/tmp/bloat_reports/
60109
61110
- name: Uploading Size Reports
62111
uses: ./.github/actions/upload-size-reports
63112
if: ${{ !env.ACT }}
64113
with:
65-
platform-name: linux
114+
platform-name: cross-platform

Cargo.toml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ members = [
88

99
exclude = ["tools/tlv", "xtask"]
1010

11-
[profile.release]
12-
opt-level = "z"
13-
1411
[profile.dev]
1512
debug = true
1613
opt-level = "z"
1714

18-
[profile.flamegraph]
19-
inherits = "release"
20-
debug = true
15+
[profile.release]
16+
opt-level = "z"
17+
debug = 0
18+
debug-assertions = false
19+
codegen-units = 1 # LLVM can perform better optimizations using a single thread
20+
lto = "fat"
21+
incremental = false
22+
overflow-checks = false

bloat-check/.cargo/config.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[build]
2+
#target = "thumbv7em-none-eabi"
3+
4+
[unstable]
5+
#build-std-features = ["panic_immediate_abort"]
6+
#build-std = ["core", "std", "panic_abort"]
7+
8+
[env]
9+
DEFMT_LOG = "info"
10+
RUST_LOG = "info"

bloat-check/Cargo.toml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
[package]
2+
name = "rs-matter-bloat-check"
3+
version = "0.1.0"
4+
edition = "2021"
5+
license = "MIT OR Apache-2.0"
6+
7+
[[bin]]
8+
name = "bloat-check"
9+
10+
[workspace]
11+
12+
[profile.dev]
13+
debug = true
14+
opt-level = "z"
15+
16+
[profile.release]
17+
opt-level = "z"
18+
debug = 0
19+
debug-assertions = false
20+
codegen-units = 1 # LLVM can perform better optimizations using a single thread
21+
lto = "fat"
22+
incremental = false
23+
overflow-checks = false
24+
25+
[features]
26+
defmt = []
27+
log = []
28+
29+
[dependencies]
30+
embassy-futures = "0.1"
31+
static_cell = "1"
32+
critical-section = "1"
33+
embassy-executor = { version = "0.9", features = ["executor-thread"] }
34+
rs-matter = { path = "../rs-matter", default-features = false, features = ["rustcrypto"] }
35+
36+
[target.'cfg(not(target_os = "none"))'.dependencies]
37+
log = { version = "0.4", features = ["max_level_info"] }
38+
simple_logger = "5"
39+
embassy-sync = { version = "0.7", features = ["log"] }
40+
embassy-time = { version = "0.5", features = ["std", "log"] }
41+
embassy-executor = { version = "0.9", features = ["arch-std", "log"] }
42+
critical-section = { version = "1", features = ["std"] }
43+
rs-matter = { path = "../rs-matter", default-features = false, features = ["log"] }
44+
45+
[target.'cfg(target_os = "none")'.dependencies]
46+
defmt = "0.3"
47+
embassy-sync = { version = "0.7", features = ["defmt"] }
48+
embassy-time = { version = "0.5", features = ["defmt"] }
49+
embassy-executor = { version = "0.9", features = ["defmt"] }
50+
embedded-alloc = "0.6"
51+
rtt-target = { version = "0.6", features = ["defmt"] }
52+
panic-rtt-target = "0.2"
53+
rs-matter = { path = "../rs-matter", default-features = false, features = ["defmt"] }
54+
55+
[target.'cfg(all(target_arch = "arm", target_os = "none"))'.dependencies]
56+
cortex-m = { version = "0.7.6", features = ["critical-section-single-core" ] }
57+
cortex-m-rt = "0.7"
58+
embassy-executor = { version = "0.9", features = ["arch-cortex-m"] }
59+
60+
[target.thumbv7em-none-eabi.dependencies]
61+
hal = { package = "embassy-nrf", version = "0.8", default-features = false, features = ["defmt", "time-driver-rtc1", "time", "nrf52840"] }
62+
63+
[target.thumbv6m-none-eabi.dependencies]
64+
hal = { package = "embassy-rp", version = "0.8", features = ["defmt", "unstable-pac", "time-driver", "rp2040"] }
65+
66+
[target.riscv32imac-unknown-none-elf.dependencies]
67+
hal = { package = "esp-hal", version = "=1.0.0-rc.1", features = ["defmt", "exception-handler", "unstable", "esp32c6"] }
68+
esp-rtos = { version = "0.1.0", features = ["embassy", "esp32c6"] }
69+
#embassy-executor = { version = "0.9", features = ["riscv32"] }

bloat-check/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# rs-matter-bloat-check
2+
3+
This project builds an executable which serves as a reference for checking the code and data footprint of `rs-matter`.

bloat-check/build.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//! This build script copies the `memory.x` file from the crate root into
2+
//! a directory where the linker can always find it at build time.
3+
//! For many projects this is optional, as the linker always searches the
4+
//! project root directory -- wherever `Cargo.toml` is. However, if you
5+
//! are using a workspace or have a more complicated build setup, this
6+
//! build script becomes required. Additionally, by requesting that
7+
//! Cargo re-run the build script whenever `memory.x` is changed,
8+
//! updating `memory.x` ensures a rebuild of the application with the
9+
//! new memory settings.
10+
11+
use std::env;
12+
use std::fs::File;
13+
use std::io::Write;
14+
use std::path::PathBuf;
15+
16+
fn main() {
17+
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
18+
19+
if target_arch == "arm" {
20+
let target = env::var("TARGET").unwrap();
21+
cortex_m(target == "thumbv7em-none-eabi");
22+
} else if target_arch == "riscv32" {
23+
riscv32();
24+
}
25+
}
26+
27+
fn cortex_m(nrf: bool) {
28+
// Put `memory.x` in our output directory and ensure it's
29+
// on the linker search path.
30+
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
31+
File::create(out.join("memory.x"))
32+
.unwrap()
33+
.write_all(if nrf {
34+
include_bytes!("memory-nrf52.x")
35+
} else {
36+
include_bytes!("memory-rp0.x")
37+
})
38+
.unwrap();
39+
println!("cargo:rustc-link-search={}", out.display());
40+
41+
// By default, Cargo will re-run a build script whenever
42+
// any file in the project changes. By specifying `memory.x`
43+
// here, we ensure the build script is only re-run when
44+
// `memory.x` is changed.
45+
println!("cargo:rerun-if-changed=memory.x");
46+
47+
println!("cargo:rustc-link-arg-bins=--nmagic");
48+
println!("cargo:rustc-link-arg-bins=-Tlink.x");
49+
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
50+
}
51+
52+
fn riscv32() {
53+
println!("cargo:rustc-link-arg=-Tdefmt.x");
54+
// make sure linkall.x is the last linker script (otherwise might cause problems with flip-link)
55+
println!("cargo:rustc-link-arg=-Tlinkall.x");
56+
}

bloat-check/memory-nrf52.x

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
MEMORY
2+
{
3+
FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
4+
RAM : ORIGIN = 0x20000000, LENGTH = 256K
5+
}

bloat-check/memory-rp0.x

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
MEMORY {
2+
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
3+
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
4+
5+
/* Pick one of the two options for RAM layout */
6+
7+
/* OPTION A: Use all RAM banks as one big block */
8+
/* Reasonable, unless you are doing something */
9+
/* really particular with DMA or other concurrent */
10+
/* access that would benefit from striping */
11+
RAM : ORIGIN = 0x20000000, LENGTH = 264K
12+
13+
/* OPTION B: Keep the unstriped sections separate */
14+
/* RAM: ORIGIN = 0x20000000, LENGTH = 256K */
15+
/* SCRATCH_A: ORIGIN = 0x20040000, LENGTH = 4K */
16+
/* SCRATCH_B: ORIGIN = 0x20041000, LENGTH = 4K */
17+
}

0 commit comments

Comments
 (0)