Skip to content

Commit 318e514

Browse files
committed
Remove RwLock and use a OnceCell instead
Doing this results ~90-100ms less overhead on average over a set of writing a burst of logs from a single thread. Closes #24
1 parent c20ec25 commit 318e514

File tree

2 files changed

+16
-23
lines changed

2 files changed

+16
-23
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ default = ["regex"]
1616
regex = ["env_logger/regex"]
1717

1818
[dependencies]
19-
lazy_static = "1.4"
19+
once_cell = "1.9"
2020

2121
[dependencies.log]
2222
version = "0.4"

src/lib.rs

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,13 @@
6565
6666
#[cfg(target_os = "android")]
6767
extern crate android_log_sys as log_ffi;
68-
#[macro_use]
69-
extern crate lazy_static;
68+
extern crate once_cell;
69+
use once_cell::sync::OnceCell;
7070
#[macro_use]
7171
extern crate log;
7272

7373
extern crate env_logger;
7474

75-
use std::sync::RwLock;
76-
7775
#[cfg(target_os = "android")]
7876
use log_ffi::LogPriority;
7977
use log::{Level, Log, Metadata, Record};
@@ -105,21 +103,20 @@ fn android_log(_priority: Level, _tag: &CStr, _msg: &CStr) {}
105103

106104
/// Underlying android logger backend
107105
pub struct AndroidLogger {
108-
config: RwLock<Config>,
106+
config: OnceCell<Config>,
109107
}
110108

111109
impl AndroidLogger {
112110
/// Create new logger instance from config
113111
pub fn new(config: Config) -> AndroidLogger {
114112
AndroidLogger {
115-
config: RwLock::new(config),
113+
config: OnceCell::from(config),
116114
}
117115
}
118116
}
119117

120-
lazy_static! {
121-
static ref ANDROID_LOGGER: AndroidLogger = AndroidLogger::default();
122-
}
118+
119+
static ANDROID_LOGGER: OnceCell<AndroidLogger> = OnceCell::new();
123120

124121
const LOGGING_TAG_MAX_LEN: usize = 23;
125122
const LOGGING_MSG_MAX_LEN: usize = 4000;
@@ -128,7 +125,7 @@ impl Default for AndroidLogger {
128125
/// Create a new logger with default config
129126
fn default() -> AndroidLogger {
130127
AndroidLogger {
131-
config: RwLock::new(Config::default()),
128+
config: OnceCell::from(Config::default()),
132129
}
133130
}
134131
}
@@ -140,8 +137,7 @@ impl Log for AndroidLogger {
140137

141138
fn log(&self, record: &Record) {
142139
let config = self.config
143-
.read()
144-
.expect("failed to acquire android_log filter lock for read");
140+
.get_or_init(Config::default);
145141

146142
if !config.filter_matches(record) {
147143
return;
@@ -423,7 +419,7 @@ impl<'a> fmt::Write for PlatformLogWriter<'a> {
423419
/// This action does not require initialization. However, without initialization it
424420
/// will use the default filter, which allows all logs.
425421
pub fn log(record: &Record) {
426-
ANDROID_LOGGER.log(record)
422+
ANDROID_LOGGER.get_or_init(AndroidLogger::default).log(record)
427423
}
428424

429425
/// Initializes the global logger with an android logger.
@@ -434,16 +430,13 @@ pub fn log(record: &Record) {
434430
/// It is ok to call this at the activity creation, and it will be
435431
/// repeatedly called on every lifecycle restart (i.e. screen rotation).
436432
pub fn init_once(config: Config) {
437-
if let Err(err) = log::set_logger(&*ANDROID_LOGGER) {
433+
let log_level = config.log_level;
434+
let logger = ANDROID_LOGGER.get_or_init(|| AndroidLogger::new(config));
435+
436+
if let Err(err) = log::set_logger(logger) {
438437
debug!("android_logger: log::set_logger failed: {}", err);
439-
} else {
440-
if let Some(level) = config.log_level {
441-
log::set_max_level(level.to_level_filter());
442-
}
443-
*ANDROID_LOGGER
444-
.config
445-
.write()
446-
.expect("failed to acquire android_log filter lock for write") = config;
438+
} else if let Some(level) = log_level {
439+
log::set_max_level(level.to_level_filter());
447440
}
448441
}
449442

0 commit comments

Comments
 (0)