Skip to content

Commit

Permalink
core, subscriber: migrate from lazy_static to once_cell (#2147)
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
james7132 committed Jun 6, 2022
1 parent 2603ab2 commit 10da627
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 63 deletions.
4 changes: 2 additions & 2 deletions tracing-core/Cargo.toml
Expand Up @@ -29,13 +29,13 @@ rust-version = "1.49.0"
[features]
default = ["std"]
alloc = []
std = ["lazy_static", "alloc"]
std = ["once_cell", "alloc"]

[badges]
maintenance = { status = "actively-developed" }

[dependencies]
lazy_static = { version = "1.0.2", optional = true }
once_cell = { version = "1.12", optional = true }

[package.metadata.docs.rs]
all-features = true
Expand Down
12 changes: 5 additions & 7 deletions tracing-core/src/callsite.rs
Expand Up @@ -158,7 +158,7 @@ pub use self::inner::{rebuild_interest_cache, register};
#[cfg(feature = "std")]
mod inner {
use super::*;
use lazy_static::lazy_static;
use once_cell::sync::Lazy;
use std::sync::RwLock;
use std::vec::Vec;

Expand All @@ -169,12 +169,10 @@ mod inner {
dispatchers: RwLock<Dispatchers>,
}

lazy_static! {
static ref REGISTRY: Registry = Registry {
callsites: LinkedList::new(),
dispatchers: RwLock::new(Vec::new()),
};
}
static REGISTRY: Lazy<Registry> = Lazy::new(|| Registry {
callsites: LinkedList::new(),
dispatchers: RwLock::new(Vec::new()),
});

/// Clear and reregister interest on every [`Callsite`]
///
Expand Down
4 changes: 2 additions & 2 deletions tracing-core/src/dispatch.rs
Expand Up @@ -550,11 +550,11 @@ impl Dispatch {
/// with access to `liballoc` or the Rust standard library are encouraged to
/// use [`Dispatch::new`] rather than `from_static`. `no_std` users who
/// cannot allocate or do not have access to `liballoc` may want to consider
/// the [`lazy_static`] crate, or another library which allows lazy
/// the [`once_cell`] crate, or another library which allows lazy
/// initialization of statics.
///
/// [collector]: super::collect::Collect
/// [`lazy_static`]: https://crates.io/crates/lazy_static
/// [`once_cell`]: https://crates.io/crates/once_cell
pub fn from_static(collector: &'static (dyn Collect + Send + Sync)) -> Self {
#[cfg(feature = "alloc")]
let me = Self {
Expand Down
2 changes: 1 addition & 1 deletion tracing-flame/Cargo.toml
Expand Up @@ -28,7 +28,7 @@ smallvec = ["tracing-subscriber/smallvec"]
[dependencies]
tracing-subscriber = { path = "../tracing-subscriber", version = "0.3", default-features = false, features = ["registry", "fmt"] }
tracing = { path = "../tracing", version = "0.2", default-features = false, features = ["std"] }
lazy_static = "1.3.0"
once_cell = "1.12"

[dev-dependencies]
tempfile = "3"
6 changes: 2 additions & 4 deletions tracing-flame/src/lib.rs
Expand Up @@ -137,7 +137,7 @@
pub use error::Error;

use error::Kind;
use lazy_static::lazy_static;
use once_cell::sync::Lazy;
use std::cell::Cell;
use std::fmt;
use std::fmt::Write as _;
Expand All @@ -158,9 +158,7 @@ use tracing_subscriber::Subscribe;

mod error;

lazy_static! {
static ref START: Instant = Instant::now();
}
static START: Lazy<Instant> = Lazy::new(Instant::now);

thread_local! {
static LAST_EVENT: Cell<Instant> = Cell::new(*START);
Expand Down
2 changes: 1 addition & 1 deletion tracing-log/Cargo.toml
Expand Up @@ -25,7 +25,7 @@ log-tracer = []
[dependencies]
tracing-core = { path = "../tracing-core", version = "0.2"}
log = { version = "0.4" }
lazy_static = "1.3.0"
once_cell = "1.12"
env_logger = { version = "0.8", optional = true }

[dev-dependencies]
Expand Down
14 changes: 6 additions & 8 deletions tracing-log/src/lib.rs
Expand Up @@ -125,7 +125,7 @@
unused_parens,
while_true
)]
use lazy_static::lazy_static;
use once_cell::sync::Lazy;

use std::{fmt, io};

Expand Down Expand Up @@ -319,13 +319,11 @@ log_cs!(
ErrorCallsite
);

lazy_static! {
static ref TRACE_FIELDS: Fields = Fields::new(&TRACE_CS);
static ref DEBUG_FIELDS: Fields = Fields::new(&DEBUG_CS);
static ref INFO_FIELDS: Fields = Fields::new(&INFO_CS);
static ref WARN_FIELDS: Fields = Fields::new(&WARN_CS);
static ref ERROR_FIELDS: Fields = Fields::new(&ERROR_CS);
}
static TRACE_FIELDS: Lazy<Fields> = Lazy::new(|| Fields::new(&TRACE_CS));
static DEBUG_FIELDS: Lazy<Fields> = Lazy::new(|| Fields::new(&DEBUG_CS));
static INFO_FIELDS: Lazy<Fields> = Lazy::new(|| Fields::new(&INFO_CS));
static WARN_FIELDS: Lazy<Fields> = Lazy::new(|| Fields::new(&WARN_CS));
static ERROR_FIELDS: Lazy<Fields> = Lazy::new(|| Fields::new(&ERROR_CS));

fn level_to_cs(level: Level) -> (&'static dyn Callsite, &'static Fields) {
match level {
Expand Down
4 changes: 2 additions & 2 deletions tracing-subscriber/Cargo.toml
Expand Up @@ -27,7 +27,7 @@ rust-version = "1.49.0"
default = ["smallvec", "fmt", "ansi", "tracing-log", "std"]
alloc = ["tracing-core/alloc"]
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"]
ansi = ["fmt", "ansi_term"]
registry = ["sharded-slab", "thread_local", "std"]
Expand All @@ -44,7 +44,7 @@ tracing = { optional = true, path = "../tracing", version = "0.2", default-featu
matchers = { optional = true, version = "0.1.0" }
regex = { optional = true, version = "1", default-features = false, features = ["std"] }
smallvec = { optional = true, version = "1" }
lazy_static = { optional = true, version = "1" }
once_cell = { optional = true, version = "1.12" }

# fmt
tracing-log = { path = "../tracing-log", version = "0.2", optional = true, default-features = false, features = ["log-tracer", "std"] }
Expand Down
70 changes: 34 additions & 36 deletions tracing-subscriber/src/filter/env/directive.rs
Expand Up @@ -4,7 +4,7 @@ use crate::filter::{
env::{field, FieldMap},
level::LevelFilter,
};
use lazy_static::lazy_static;
use once_cell::sync::Lazy;
use regex::Regex;
use std::{cmp::Ordering, fmt, iter::FromIterator, str::FromStr};
use tracing_core::{span, Level, Metadata};
Expand Down Expand Up @@ -120,41 +120,39 @@ impl Directive {
}

pub(super) fn parse(from: &str, regex: bool) -> Result<Self, ParseError> {
lazy_static! {
static ref DIRECTIVE_RE: Regex = Regex::new(
r"(?x)
^(?P<global_level>(?i:trace|debug|info|warn|error|off|[0-5]))$ |
# ^^^.
# `note: we match log level names case-insensitively
^
(?: # target name or span name
(?P<target>[\w:-]+)|(?P<span>\[[^\]]*\])
){1,2}
(?: # level or nothing
=(?P<level>(?i:trace|debug|info|warn|error|off|[0-5]))?
# ^^^.
# `note: we match log level names case-insensitively
)?
$
"
)
.unwrap();
static ref SPAN_PART_RE: Regex =
Regex::new(r#"(?P<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?"#).unwrap();
static ref FIELD_FILTER_RE: Regex =
// TODO(eliza): this doesn't _currently_ handle value matchers that include comma
// characters. We should fix that.
Regex::new(r#"(?x)
(
# field name
[[:word:]][[[:word:]]\.]*
# value part (optional)
(?:=[^,]+)?
)
# trailing comma or EOS
(?:,\s?|$)
"#).unwrap();
}
static DIRECTIVE_RE: Lazy<Regex> = Lazy::new(|| Regex::new(
r"(?x)
^(?P<global_level>(?i:trace|debug|info|warn|error|off|[0-5]))$ |
# ^^^.
# `note: we match log level names case-insensitively
^
(?: # target name or span name
(?P<target>[\w:-]+)|(?P<span>\[[^\]]*\])
){1,2}
(?: # level or nothing
=(?P<level>(?i:trace|debug|info|warn|error|off|[0-5]))?
# ^^^.
# `note: we match log level names case-insensitively
)?
$
"
)
.unwrap());
static SPAN_PART_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r#"(?P<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?"#).unwrap());
static FIELD_FILTER_RE: Lazy<Regex> =
// TODO(eliza): this doesn't _currently_ handle value matchers that include comma
// characters. We should fix that.
Lazy::new(|| Regex::new(r#"(?x)
(
# field name
[[:word:]][[[:word:]]\.]*
# value part (optional)
(?:=[^,]+)?
)
# trailing comma or EOS
(?:,\s?|$)
"#).unwrap());

let caps = DIRECTIVE_RE.captures(from).ok_or_else(ParseError::new)?;

Expand Down

0 comments on commit 10da627

Please sign in to comment.