-
Notifications
You must be signed in to change notification settings - Fork 717
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: optimize for binary size #1425
Comments
I don't think removing metadata fields will make a significant impact on binary size. Instead, I think a majority --- or perhaps all --- of the increased binary size you're seeing is due to the amount of code that is generated by macro invocations. There was a previous attempt at fixing this, by moving the path where a span/event is actually recorded behind a function call so that the recording code isn't monomorphized at every macro invocation (see #943). Unfortunately, this inadvertently caused a breaking change, and had to be reverted (see #987). In Fortunately, in This means we can significantly reduce how much Incidentally, the file name, line number, and module paths on |
Thanks, @hawkw. The new TIL, I'm too naive, haha. |
In my experience, the data section of binaries is packed with strings that refer to the source code. For example, running the following command readelf -x .rodata target/armv7-unknown-linux-gnueabihf/release/binary-name yields the following output:
Each one of those line numbers refer to a tracing::{info,trace,debug,error} macro invocation! Removing these strings would significantly reduce the binary size for my application. Is there any feature flags, either from tracing = { workspace = "0.1.40", features = ["std", "attributes"] }
tracing-subscriber = { workspace = "0.3.18", default-features = false, features = ["std", "fmt", "registry", "json"] } PS: I already followed these suggestions: #1925 (comment) PS2: I found the culprit Line 857 in 690a9a6
|
These are the default names of events. You could manually set Using features to control this is questionable because features are additive and so any crate anywhere in your dependency tree could enable a feature and you have no way to disable it. But I think it's reasonable to consider changing the default event name for 0.2 since this would be most likely breaking. There is another mechanism to obtain the filename and line number so it is probably wasteful if every single |
But that would only affect my crate, which is the tip of the iceberg.
Indeed, these names are being generated for every single consumer of tracing and appended to my binary. For example, the crate async-io consumes tracing (https://crates.io/crates/async-io/2.3.2/dependencies). Running the following command on a binary that depends on async-io readelf -p .rodata target/armv7-unknown-linux-gnueabihf/release/az-mqtt | rg --regexp="event.*async_io.*.rs:\d+" yields this: [ 3070] sleeping for uscannot initialize I/O event notification ready wakersasync_io::main_loopevent /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/driver.rs:68event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/driver.rs:83event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/driver.rs:85async_io::block_onevent /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/driver.rs:203event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/driver.rs:209event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/driver.rs:242event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/driver.rs:247event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/driver.rs:252event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/driver.rs:258event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/driver.rs:277process_timersasync_io::reactorevent /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/reactor.rs:241reactevent /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/reactor.rs:359event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/reactor.rs:544event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/reactor.rs:564event /cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/reactor.rs:584Shouldn't be able to borrow parker reentrantlymust listen() on event listener before waitinglistener was never inserted into the list/cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-4.0.3/src/std.rsinternal error: entered unreachable code: Invalid stateinvalid key/cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-2.3.2/src/reactor.rsreadable_ownedwritable_ownedfuture polled after completion/cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-5.3.0/src/lib.rs/cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-4.0.3/src/lib.rsEventListener was not inserted into the linked list, make sure you're not polling EventListener/listener! after it has finished/cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-5.3.0/src/std.rstag already taken/cargo/registry/src/index.crates.io-6f17d22bba15001f/concurrent-queue-2.5.0/src/bounded.rs/cargo/registry/src/index.crates.io-6f17d22bba15001f/concurrent-queue-2.5.0/src/unbounded.rs Notice the prefix for all of these. They could be removed, at least, |
Comparing to the
log
crate,tracing
is so powerful and elegant. However,tracing
also brings more binary size to the application due to the more complex expanded macro codes. I have a simple binary size test againsttracing
andlog
.Here is the source code. For 1k lines of
info!("Hello World!");
macro called,tracing
is nearly 2x larger binary size than thelog
(in release mode, w/ostrip
).P.S. We recently replaced the
log
withtracing
in our company project. What overwhelmed us is that we got 10 Mib large size than before! 😲Proposal
Optimize the binary size without comprising the features, elegance, and performance.
I only have few thoughts right now:
name
field ofMetadata
is useful to theEvent
, neither thefile
,line
, andmodule_path
are useful to theSpan
? We really need to share the sameMetadata
struct forEvent
andSpan
?level
field forSpan
, I still in favor of level-lessSpan
. I believe this can reduce the complexity and is beneficial to binary size.Alternative
Maybe we can have a
tracing-lite
crate, which is binary size friendly but missing some features?The text was updated successfully, but these errors were encountered: