core, subscriber: migrate from lazy_static to once_cell (#2147)

Replace `lazy_static` with `once_cell`. Fixes #2146.

## Motivation

`lazy_static!`, while a declarative macro, is a macro nonetheless. It
can add quite a bit of additional compilation time cost.
`once_cell::sync::Lazy` does the same thing with generics, and can be
used more flexibly (i.e. non-static lazily initialized values), and has
been proposed to be added to `std` (see linked issue).

I'm trying to reduce the compile time and dependency tree complexity of
a dependent project: [bevy](https://bevyengine.org), which is using
tracing. `lazy_static` and `once_cell` are both in our dependency tree
and both end up doing the same thing.

## Solution

Migrate to `once_cell`.
This commit is contained in:
James Liu 2022-06-06 10:32:41 -07:00 committed by Eliza Weisman
parent 0130df7ca2
commit 29b265dd9c
12 changed files with 66 additions and 82 deletions

View File

@ -32,7 +32,7 @@ futures = "0.3"
tokio = { version = "1.1", features = ["full"] } tokio = { version = "1.1", features = ["full"] }
# env-logger example # env-logger example
env_logger = "0.7" env_logger = "0.9"
# tower examples # tower examples
tower = { version = "0.4.4", features = ["full"] } tower = { version = "0.4.4", features = ["full"] }

View File

@ -92,17 +92,9 @@ async fn echo(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
use tracing_log::env_logger::BuilderExt;
let subscriber = tracing_subscriber::fmt() let subscriber = tracing_subscriber::fmt()
.with_max_level(Level::TRACE) .with_max_level(Level::TRACE)
.finish(); .finish();
let mut builder = env_logger::Builder::new();
builder
.filter(Some("hyper_echo"), log::LevelFilter::Off)
.filter(Some("hyper"), log::LevelFilter::Trace)
.emit_traces() // from `tracing_log::env_logger::BuilderExt`
.try_init()?;
tracing::subscriber::set_global_default(subscriber)?; tracing::subscriber::set_global_default(subscriber)?;
let local_addr: std::net::SocketAddr = ([127, 0, 0, 1], 3000).into(); let local_addr: std::net::SocketAddr = ([127, 0, 0, 1], 3000).into();

View File

@ -28,13 +28,13 @@ rust-version = "1.49.0"
[features] [features]
default = ["std", "valuable/std"] default = ["std", "valuable/std"]
std = ["lazy_static"] std = ["once_cell"]
[badges] [badges]
maintenance = { status = "actively-developed" } maintenance = { status = "actively-developed" }
[dependencies] [dependencies]
lazy_static = { version = "1.0.2", optional = true } once_cell = { version = "1.12", optional = true }
[target.'cfg(tracing_unstable)'.dependencies] [target.'cfg(tracing_unstable)'.dependencies]
valuable = { version = "0.1.0", optional = true, default_features = false } valuable = { version = "0.1.0", optional = true, default_features = false }

View File

@ -253,6 +253,11 @@ static CALLSITES: Callsites = Callsites {
static DISPATCHERS: Dispatchers = Dispatchers::new(); static DISPATCHERS: Dispatchers = Dispatchers::new();
#[cfg(feature = "std")]
static LOCKED_CALLSITES: once_cell::sync::Lazy<Mutex<Vec<&'static dyn Callsite>>> =
once_cell::sync::Lazy::new(Default::default);
#[cfg(not(feature = "std"))]
crate::lazy_static! { crate::lazy_static! {
static ref LOCKED_CALLSITES: Mutex<Vec<&'static dyn Callsite>> = Mutex::new(Vec::new()); static ref LOCKED_CALLSITES: Mutex<Vec<&'static dyn Callsite>> = Mutex::new(Vec::new());
} }
@ -510,6 +515,7 @@ mod private {
#[cfg(feature = "std")] #[cfg(feature = "std")]
mod dispatchers { mod dispatchers {
use crate::dispatcher; use crate::dispatcher;
use once_cell::sync::Lazy;
use std::sync::{ use std::sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
RwLock, RwLockReadGuard, RwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard,
@ -519,9 +525,8 @@ mod dispatchers {
has_just_one: AtomicBool, has_just_one: AtomicBool,
} }
crate::lazy_static! { static LOCKED_DISPATCHERS: Lazy<RwLock<Vec<dispatcher::Registrar>>> =
static ref LOCKED_DISPATCHERS: RwLock<Vec<dispatcher::Registrar>> = RwLock::new(Vec::new()); Lazy::new(Default::default);
}
pub(super) enum Rebuilder<'a> { pub(super) enum Rebuilder<'a> {
JustOne, JustOne,

View File

@ -254,10 +254,6 @@ macro_rules! metadata {
}; };
} }
// when `std` is enabled, use the `lazy_static` crate from crates.io
#[cfg(feature = "std")]
pub(crate) use lazy_static::lazy_static;
// Facade module: `no_std` uses spinlocks, `std` uses the mutexes in the standard library // Facade module: `no_std` uses spinlocks, `std` uses the mutexes in the standard library
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
#[macro_use] #[macro_use]

View File

@ -28,7 +28,8 @@ smallvec = ["tracing-subscriber/smallvec"]
[dependencies] [dependencies]
tracing-subscriber = { path = "../tracing-subscriber", version = "0.3", default-features = false, features = ["registry", "fmt"] } tracing-subscriber = { path = "../tracing-subscriber", version = "0.3", default-features = false, features = ["registry", "fmt"] }
tracing = { path = "../tracing", version = "0.1.12", default-features = false, features = ["std"] } tracing = { path = "../tracing", version = "0.1.12", default-features = false, features = ["std"] }
lazy_static = "1.3.0" once_cell = "1.12"
[dev-dependencies] [dev-dependencies]
tempfile = "3" tempfile = "3"

View File

@ -137,7 +137,7 @@
pub use error::Error; pub use error::Error;
use error::Kind; use error::Kind;
use lazy_static::lazy_static; use once_cell::sync::Lazy;
use std::cell::Cell; use std::cell::Cell;
use std::fmt; use std::fmt;
use std::fmt::Write as _; use std::fmt::Write as _;
@ -158,9 +158,7 @@ use tracing_subscriber::Layer;
mod error; mod error;
lazy_static! { static START: Lazy<Instant> = Lazy::new(Instant::now);
static ref START: Instant = Instant::now();
}
thread_local! { thread_local! {
static LAST_EVENT: Cell<Instant> = Cell::new(*START); static LAST_EVENT: Cell<Instant> = Cell::new(*START);

View File

@ -27,8 +27,8 @@ interest-cache = ["lru", "ahash"]
[dependencies] [dependencies]
tracing-core = { path = "../tracing-core", version = "0.1.17"} tracing-core = { path = "../tracing-core", version = "0.1.17"}
log = { version = "0.4" } log = { version = "0.4" }
lazy_static = "1.3.0" once_cell = "1.12"
env_logger = { version = "0.7", optional = true } env_logger = { version = "0.8", optional = true }
lru = { version = "0.7.0", optional = true } lru = { version = "0.7.0", optional = true }
ahash = { version = "0.7.4", optional = true } ahash = { version = "0.7.4", optional = true }

View File

@ -1,6 +1,7 @@
use ahash::AHasher; use ahash::AHasher;
use log::{Level, Metadata}; use log::{Level, Metadata};
use lru::LruCache; use lru::LruCache;
use once_cell::sync::Lazy;
use std::cell::RefCell; use std::cell::RefCell;
use std::hash::Hasher; use std::hash::Hasher;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
@ -140,12 +141,10 @@ static SENTINEL_METADATA: tracing_core::Metadata<'static> = tracing_core::Metada
tracing_core::metadata::Kind::EVENT, tracing_core::metadata::Kind::EVENT,
); );
lazy_static::lazy_static! { static CONFIG: Lazy<Mutex<InterestCacheConfig>> = Lazy::new(|| {
static ref CONFIG: Mutex<InterestCacheConfig> = {
tracing_core::callsite::register(&SENTINEL_CALLSITE); tracing_core::callsite::register(&SENTINEL_CALLSITE);
Mutex::new(InterestCacheConfig::disabled()) Mutex::new(InterestCacheConfig::disabled())
}; });
}
thread_local! { thread_local! {
static STATE: RefCell<State> = { static STATE: RefCell<State> = {
@ -236,10 +235,7 @@ mod tests {
fn lock_for_test() -> impl Drop { fn lock_for_test() -> impl Drop {
// We need to make sure only one test runs at a time. // We need to make sure only one test runs at a time.
static LOCK: Lazy<Mutex<()>> = Lazy::new(Mutex::new);
lazy_static::lazy_static! {
static ref LOCK: Mutex<()> = Mutex::new(());
}
match LOCK.lock() { match LOCK.lock() {
Ok(guard) => guard, Ok(guard) => guard,

View File

@ -128,7 +128,7 @@
unused_parens, unused_parens,
while_true while_true
)] )]
use lazy_static::lazy_static; use once_cell::sync::Lazy;
use std::{fmt, io}; use std::{fmt, io};
@ -346,13 +346,11 @@ log_cs!(
ErrorCallsite ErrorCallsite
); );
lazy_static! { static TRACE_FIELDS: Lazy<Fields> = Lazy::new(|| Fields::new(&TRACE_CS));
static ref TRACE_FIELDS: Fields = Fields::new(&TRACE_CS); static DEBUG_FIELDS: Lazy<Fields> = Lazy::new(|| Fields::new(&DEBUG_CS));
static ref DEBUG_FIELDS: Fields = Fields::new(&DEBUG_CS); static INFO_FIELDS: Lazy<Fields> = Lazy::new(|| Fields::new(&INFO_CS));
static ref INFO_FIELDS: Fields = Fields::new(&INFO_CS); static WARN_FIELDS: Lazy<Fields> = Lazy::new(|| Fields::new(&WARN_CS));
static ref WARN_FIELDS: Fields = Fields::new(&WARN_CS); static ERROR_FIELDS: Lazy<Fields> = Lazy::new(|| Fields::new(&ERROR_CS));
static ref ERROR_FIELDS: Fields = Fields::new(&ERROR_CS);
}
fn level_to_cs(level: Level) -> (&'static dyn Callsite, &'static Fields) { fn level_to_cs(level: Level) -> (&'static dyn Callsite, &'static Fields) {
match level { match level {

View File

@ -27,7 +27,7 @@ rust-version = "1.49.0"
default = ["smallvec", "fmt", "ansi", "tracing-log", "std"] default = ["smallvec", "fmt", "ansi", "tracing-log", "std"]
alloc = [] alloc = []
std = ["alloc", "tracing-core/std"] std = ["alloc", "tracing-core/std"]
env-filter = ["matchers", "regex", "lazy_static", "tracing", "std", "thread_local"] env-filter = ["matchers", "regex", "once_cell", "tracing", "std", "thread_local"]
fmt = ["registry", "std"] fmt = ["registry", "std"]
ansi = ["fmt", "ansi_term"] ansi = ["fmt", "ansi_term"]
registry = ["sharded-slab", "thread_local", "std"] registry = ["sharded-slab", "thread_local", "std"]
@ -45,7 +45,7 @@ tracing = { optional = true, path = "../tracing", version = "0.1", default-featu
matchers = { optional = true, version = "0.1.0" } matchers = { optional = true, version = "0.1.0" }
regex = { optional = true, version = "1", default-features = false, features = ["std"] } regex = { optional = true, version = "1", default-features = false, features = ["std"] }
smallvec = { optional = true, version = "1.2.0" } smallvec = { optional = true, version = "1.2.0" }
lazy_static = { optional = true, version = "1" } once_cell = { optional = true, version = "1.12" }
# fmt # fmt
tracing-log = { path = "../tracing-log", version = "0.1.2", optional = true, default-features = false, features = ["log-tracer", "std"] } tracing-log = { path = "../tracing-log", version = "0.1.2", optional = true, default-features = false, features = ["log-tracer", "std"] }
@ -58,7 +58,7 @@ serde = { version = "1.0", optional = true }
tracing-serde = { path = "../tracing-serde", version = "0.1.3", optional = true } tracing-serde = { path = "../tracing-serde", version = "0.1.3", optional = true }
# opt-in deps # opt-in deps
parking_lot = { version = "0.13", optional = true } parking_lot = { version = "0.12", optional = true }
# registry # registry
sharded-slab = { version = "0.1.0", optional = true } sharded-slab = { version = "0.1.0", optional = true }

View File

@ -4,7 +4,7 @@ use crate::filter::{
env::{field, FieldMap}, env::{field, FieldMap},
level::LevelFilter, level::LevelFilter,
}; };
use lazy_static::lazy_static; use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
use std::{cmp::Ordering, fmt, iter::FromIterator, str::FromStr}; use std::{cmp::Ordering, fmt, iter::FromIterator, str::FromStr};
use tracing_core::{span, Level, Metadata}; use tracing_core::{span, Level, Metadata};
@ -120,8 +120,7 @@ impl Directive {
} }
pub(super) fn parse(from: &str, regex: bool) -> Result<Self, ParseError> { pub(super) fn parse(from: &str, regex: bool) -> Result<Self, ParseError> {
lazy_static! { static DIRECTIVE_RE: Lazy<Regex> = Lazy::new(|| Regex::new(
static ref DIRECTIVE_RE: Regex = Regex::new(
r"(?x) r"(?x)
^(?P<global_level>(?i:trace|debug|info|warn|error|off|[0-5]))$ | ^(?P<global_level>(?i:trace|debug|info|warn|error|off|[0-5]))$ |
# ^^^. # ^^^.
@ -138,13 +137,13 @@ impl Directive {
$ $
" "
) )
.unwrap(); .unwrap());
static ref SPAN_PART_RE: Regex = static SPAN_PART_RE: Lazy<Regex> =
Regex::new(r#"(?P<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?"#).unwrap(); Lazy::new(|| Regex::new(r#"(?P<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?"#).unwrap());
static ref FIELD_FILTER_RE: Regex = static FIELD_FILTER_RE: Lazy<Regex> =
// TODO(eliza): this doesn't _currently_ handle value matchers that include comma // TODO(eliza): this doesn't _currently_ handle value matchers that include comma
// characters. We should fix that. // characters. We should fix that.
Regex::new(r#"(?x) Lazy::new(|| Regex::new(r#"(?x)
( (
# field name # field name
[[:word:]][[[:word:]]\.]* [[:word:]][[[:word:]]\.]*
@ -153,8 +152,7 @@ impl Directive {
) )
# trailing comma or EOS # trailing comma or EOS
(?:,\s?|$) (?:,\s?|$)
"#).unwrap(); "#).unwrap());
}
let caps = DIRECTIVE_RE.captures(from).ok_or_else(ParseError::new)?; let caps = DIRECTIVE_RE.captures(from).ok_or_else(ParseError::new)?;