Description
Bug Report
Hello, I'm investigating binary bloat in an application and I noticed that there seems to be a lot from log statements, even if I try to statically compile them away.
Version
tracing: 0.1.22
Rust: rustc 1.51.0-nightly (da305a2b0 2021-01-05)
Platform
Darwin mark 20.2.0 Darwin Kernel Version 20.2.0: Wed Dec 2 20:39:59 PST 2020; root:xnu-7195.60.75~1/RELEASE_X86_64 x86_64
Crates
tracing, tracing-log?
Description
features:
tracing = { version = "0.1", features = ["log", "release_max_level_off", "max_level_off"] }
context:
#[typetag::serde(tag = "type")]
pub trait WasiFile: fmt::Debug + Send + Write + Read + Seek + 'static + Upcastable {
fn set_last_accessed(&self, _last_accessed: __wasi_timestamp_t) {
// debug!("{:?} did nothing in WasiFile::set_last_accessed due to using the default implementation", self);
}
fn set_last_modified(&self, _last_modified: __wasi_timestamp_t) {
debug!("{:?} did nothing in WasiFile::set_last_modified due to using the default implementation", self);
}
...
This was most noticeable in this trait where the empty default methods log and then return without doing anything. This trait is implemented on a number of types and many of the types use the default implementations.
note that set_last_accessed
has been commented out as a baseline to compare against.
Running cargo bloat
without the release_max_level_off
and max_level_off
features in release mode, we get:
591B wasmer_wasi wasmer_wasi::state::types::WasiFile::set_last_modified
6B wasmer_wasi wasmer_wasi::state::types::WasiFile::set_last_accessed
with multiple entries.
Running cargo bloat
with release_max_level_off
and max_level_off
features in release mode, we get:
300B wasmer_wasi wasmer_wasi::state::types::WasiFile::set_last_modified
6B wasmer_wasi wasmer_wasi::state::types::WasiFile::set_last_accessed
So we get a reduction of about half in terms of bytes of generated code by enabling these features. I'd expect these features to be equivalent to commenting out the log statement.
cargo expanding it, we get:
fn set_last_accessed(&self, _last_accessed: __wasi_timestamp_t) {}
and
fn set_last_modified(&self, _last_modified: __wasi_timestamp_t) {
{
if !::tracing::dispatcher::has_been_set() {
{
use ::tracing::log;
let level = match ::tracing::Level::DEBUG {
::tracing::Level::ERROR => ::tracing::log::Level::Error,
::tracing::Level::WARN => ::tracing::log::Level::Warn,
::tracing::Level::INFO => ::tracing::log::Level::Info,
::tracing::Level::DEBUG => ::tracing::log::Level::Debug,
_ => ::tracing::log::Level::Trace,
};
if level <= log::STATIC_MAX_LEVEL && level <= log::max_level() {
let log_meta = log::Metadata::builder()
.level(level)
.target("wasmer_wasi::state::types")
.build();
let logger = log::logger();
if logger.enabled(&log_meta) {
logger . log ( & log :: Record :: builder ( ) . file ( Some ( "lib/wasi/src/state/types.rs" ) ) . module_path ( Some ( "wasmer_wasi::state::types" ) ) . line ( Some ( 171u32 ) ) . metadata ( log_meta ) . args ( { # [ allow ( unused_imports ) ] use :: tracing :: field :: { debug , display } ; :: core :: fmt :: Arguments :: new_v1 ( & [ "" , " " ] , & match ( & :: core :: fmt :: Arguments :: new_v1 ( & [ "" , " did nothing in WasiFile::set_last_modified due to using the default implementation" ] , & match ( & self , ) { ( arg0 , ) => [ :: core :: fmt :: ArgumentV1 :: new ( arg0 , :: core :: fmt :: Debug :: fmt ) ] , } ) , ) { ( arg0 , ) => [ :: core :: fmt :: ArgumentV1 :: new ( arg0 , :: core :: fmt :: Display :: fmt ) ] , } ) } ) . build ( ) ) ;
}
}
}
} else {
{}
};
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&& ::tracing::Level::DEBUG
<= ::tracing::level_filters::LevelFilter::current()
{
use ::tracing::__macro_support::*;
static CALLSITE: ::tracing::__macro_support::MacroCallsite = {
use ::tracing::__macro_support::MacroCallsite;
static META: ::tracing::Metadata<'static> = {
::tracing_core::metadata::Metadata::new(
"event lib/wasi/src/state/types.rs:171",
"wasmer_wasi::state::types",
::tracing::Level::DEBUG,
Some("lib/wasi/src/state/types.rs"),
Some(171u32),
Some("wasmer_wasi::state::types"),
::tracing_core::field::FieldSet::new(
&["message"],
::tracing_core::callsite::Identifier(&CALLSITE),
),
::tracing::metadata::Kind::EVENT,
)
};
MacroCallsite::new(&META)
};
let interest = CALLSITE.interest();
if !interest.is_never() && CALLSITE.is_enabled(interest) {
let meta = CALLSITE.metadata();
::tracing::Event::dispatch(meta, &{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta . fields ( ) . value_set ( & [ ( & iter . next ( ) . expect ( "FieldSet corrupted (this is a bug)" ) , Some ( & :: core :: fmt :: Arguments :: new_v1 ( & [ "" , " did nothing in WasiFile::set_last_modified due to using the default implementation" ] , & match ( & self , ) { ( arg0 , ) => [ :: core :: fmt :: ArgumentV1 :: new ( arg0 , :: core :: fmt :: Debug :: fmt ) ] , } ) as & Value ) ) ] )
});
}
}
};
}
Expected behavior is:
- When these features are set, for the macro expansion to be empty (using features to make the macros no-ops)
- OR The macro-expanded code should be reduced into "0" bytes (leaving 6 bytes total for the trait method in this case, same as the base line)
Extra context
It probably doesn't matter but the release profile was tweaked when running this:
[profile.release]
opt-level = 'z'
debug = false
debug-assertions = false
overflow-checks = false
lto = true
panic = 'abort'
incremental = false
codegen-units = 1
rpath = false
Thanks!