toml
toml copied to clipboard
Large increase in binary size after upgrading to v0.7.6
Recently, I ran a cargo update
on my project, and the release binary size jumped ~0.13MB. Relevant CI builds are https://github.com/ravenclaw900/DietPi-Dashboard/actions/runs/5523750813 (old) and https://github.com/ravenclaw900/DietPi-Dashboard/actions/runs/5524904223 (new). I am aware that this was mentioned in https://github.com/toml-rs/toml/issues/340#issuecomment-1363560789 and is a known 'regression'. I also understand that the old toml
crate was unmaintained, and didn't fully support TOML 1.0. All that to say, I am in favor of the new parser and what it does, but I'm wondering why the increase in binary size was so large and if there's anything that can be done on either end to reduce the size?
Happen to know if that was with or without debug symbols?
I ran cargo bloat
on a toml
example:
$ cargo bloat --crates --release --example decode
warning: skipping duplicate package `example` found at `/home/epage/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc
6/35ce7d7/example`
Finished release [optimized + debuginfo] target(s) in 0.02s
Analyzing target/release/examples/decode
File .text Size Crate
2.5% 52.4% 270.7KiB std
2.0% 41.6% 214.5KiB toml_edit
0.1% 1.7% 8.7KiB winnow
0.0% 0.8% 4.3KiB serde
0.0% 0.5% 2.3KiB libtest_mimic
0.0% 0.3% 1.8KiB toml_datetime
0.0% 0.3% 1.4KiB decode
0.0% 0.2% 1.0KiB regex
0.0% 0.1% 555B ignore
0.0% 0.1% 440B memchr
0.0% 0.0% 260B serde_spanned
0.0% 0.0% 133B toml
0.0% 0.0% 109B [Unknown]
0.0% 0.0% 95B hashbrown
0.0% 0.0% 83B indexmap
0.0% 0.0% 38B clap
0.0% 0.0% 5B libc
4.7% 100.0% 516.2KiB .text section size, the file size is 10.6MiB
Re-ran it with toml 0.5
$ cargo bloat --crates --release --example decode
warning: skipping duplicate package `example` found at `/home/epage/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc
6/35ce7d7/example`
Compiling toml v0.5.10
Compiling toml v0.7.6 (/home/epage/src/personal/toml/crates/toml)
Finished release [optimized + debuginfo] target(s) in 2.51s
Analyzing target/release/examples/decode
File .text Size Crate
4.1% 70.6% 270.8KiB std
1.3% 23.4% 89.6KiB toml
0.1% 2.5% 9.7KiB serde
0.0% 0.9% 3.3KiB libtest_mimic
0.0% 0.2% 761B decode
0.0% 0.2% 726B hashbrown
0.0% 0.1% 555B ignore
0.0% 0.1% 440B memchr
0.0% 0.0% 166B indexmap
0.0% 0.0% 109B [Unknown]
0.0% 0.0% 5B libc
5.7% 100.0% 383.4KiB .text section size, the file size is 6.5MiB
Note: numbers above are a result of guesswork. They are not 100% correct and never will be.
So
- old
toml
: 383 KiB total - new
toml
: 516 KiB total - diff: 133 KiB
commit 6e63746862250c6bf35c030d04e1014b1d779b40
After a couple of tweaks (#585), I dropped a little of the size
$ cargo bloat --release --example decode --crates
warning: skipping duplicate package `example` found at `/home/epage/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc
6/35ce7d7/example`
Compiling toml_edit v0.19.13 (/home/epage/src/personal/toml/crates/toml_edit)
Compiling toml v0.7.6 (/home/epage/src/personal/toml/crates/toml)
Finished release [optimized + debuginfo] target(s) in 3.31s
Analyzing target/release/examples/decode
File .text Size Crate
2.5% 53.8% 269.4KiB std
1.9% 40.1% 200.8KiB toml_edit
0.1% 1.7% 8.7KiB winnow
0.0% 0.9% 4.3KiB serde
0.0% 0.5% 2.3KiB libtest_mimic
0.0% 0.4% 1.8KiB toml_datetime
0.0% 0.3% 1.4KiB decode
0.0% 0.2% 1.0KiB regex
0.0% 0.1% 555B ignore
0.0% 0.1% 440B memchr
0.0% 0.1% 260B serde_spanned
0.0% 0.0% 133B toml
0.0% 0.0% 109B [Unknown]
0.0% 0.0% 95B hashbrown
0.0% 0.0% 83B indexmap
0.0% 0.0% 38B clap
0.0% 0.0% 5B libc
4.7% 100.0% 501.0KiB .text section size, the file size is 10.5MiB
Note: numbers above are a result of guesswork. They are not 100% correct and never will be.
From looking at the function sizes, my best guesses as to where the size is going
- Optimizations
- Error reporting
- Book keeping for format preserving
- Lots of small overhead added up
- Potentially there are multiple copies of functions in the deserialization code that could be reduced down
I should note that the example I was measuring only deserializes so all of the serialization code was optimized out.
All the debug symbols were stripped out in the builds I posted, and it should have also just been deserialization. I'll see if I can get a cargo bloat
later, any specific settings that would be helpful?
Version 0.19.12
:
cargo bloat --crates --release
Finished release [optimized] target(s) in 0.05s
Analyzing target/release/dietpi-dashboard
File .text Size Crate
7.3% 22.2% 455.0KiB std
6.4% 19.4% 399.5KiB dietpi_dashboard
2.1% 6.5% 132.7KiB toml_edit
2.1% 6.4% 131.4KiB tokio
2.1% 6.3% 128.7KiB rustls
1.9% 5.9% 122.0KiB ring
1.5% 4.6% 94.6KiB hyper
1.2% 3.7% 75.2KiB figment
1.2% 3.6% 74.8KiB [Unknown]
0.6% 1.9% 39.8KiB psutil
0.6% 1.9% 39.3KiB jsonwebtoken
0.6% 1.8% 37.3KiB serde_json
0.4% 1.3% 27.7KiB serde
0.4% 1.3% 27.2KiB tracing_subscriber
0.4% 1.2% 24.7KiB http
0.3% 0.9% 17.9KiB anyhow
0.3% 0.9% 17.7KiB zip
0.3% 0.8% 16.2KiB data_encoding
0.2% 0.7% 14.5KiB hashbrown
0.2% 0.7% 14.2KiB futures_util
2.3% 7.0% 144.5KiB And 52 more crates. Use -n N to show more.
32.7% 100.0% 2.0MiB .text section size, the file size is 6.1MiB
Version 0.19.14
:
cargo bloat --crates --release
Finished release [optimized] target(s) in 0.05s
Analyzing target/release/dietpi-dashboard
File .text Size Crate
7.3% 22.5% 455.0KiB std
6.4% 19.7% 399.5KiB dietpi_dashboard
2.1% 6.5% 131.2KiB tokio
2.1% 6.3% 128.4KiB rustls
2.0% 6.0% 122.0KiB ring
1.6% 4.8% 96.9KiB toml_edit
1.5% 4.7% 94.4KiB hyper
1.2% 3.7% 74.8KiB [Unknown]
1.2% 3.7% 74.6KiB figment
0.6% 2.0% 39.8KiB psutil
0.6% 2.0% 39.7KiB jsonwebtoken
0.6% 1.8% 37.2KiB serde_json
0.4% 1.4% 27.7KiB serde
0.4% 1.3% 27.2KiB tracing_subscriber
0.4% 1.2% 24.5KiB http
0.3% 0.9% 17.9KiB anyhow
0.3% 0.9% 17.7KiB zip
0.3% 0.8% 16.2KiB data_encoding
0.2% 0.7% 14.5KiB hashbrown
0.2% 0.7% 14.2KiB futures_util
2.4% 7.5% 150.9KiB And 55 more crates. Use -n N to show more.
32.5% 100.0% 2.0MiB .text section size, the file size is 6.1MiB
Strangely, binary size increased slightly on every target other than x86_64 after updating to toml_edit
0.19.14, though it's possible this was due to another dependency.