Skip to content
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

perf: Replace HashMap with a Vec #241

Merged
merged 1 commit into from Nov 10, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 22 additions & 11 deletions src/filter/mod.rs
Expand Up @@ -59,7 +59,6 @@
//! [`Filter::matches`]: struct.Filter.html#method.matches

use log::{Level, LevelFilter, Metadata, Record};
use std::collections::HashMap;
use std::env;
use std::fmt;
use std::mem;
Expand Down Expand Up @@ -108,7 +107,7 @@ pub struct Filter {
///
/// [`Filter`]: struct.Filter.html
pub struct Builder {
directives: HashMap<Option<String>, LevelFilter>,
directives: Vec<Directive>,
filter: Option<inner::Filter>,
built: bool,
}
Expand Down Expand Up @@ -172,7 +171,7 @@ impl Builder {
/// Initializes the filter builder with defaults.
pub fn new() -> Builder {
Builder {
directives: HashMap::new(),
directives: Vec::new(),
filter: None,
built: false,
}
Expand All @@ -189,6 +188,19 @@ impl Builder {
builder
}

/// Insert the directive replacing any directive with the same name.
fn insert_directive(&mut self, mut directive: Directive) {
if let Some(pos) = self
.directives
.iter()
.position(|d| d.name == directive.name)
{
mem::swap(&mut self.directives[pos], &mut directive);
} else {
self.directives.push(directive);
}
}

/// Adds a directive to the filter for a specific module.
pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
self.filter(Some(module), level)
Expand All @@ -204,7 +216,10 @@ impl Builder {
/// The given module (if any) will log at most the specified level provided.
/// If no module is provided then the filter will apply to all log messages.
pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
self.directives.insert(module.map(|s| s.to_string()), level);
self.insert_directive(Directive {
name: module.map(|s| s.to_string()),
level,
});
self
}

Expand All @@ -219,7 +234,7 @@ impl Builder {
self.filter = filter;

for directive in directives {
self.directives.insert(directive.name, directive.level);
self.insert_directive(directive);
}
self
}
Expand All @@ -237,12 +252,8 @@ impl Builder {
level: LevelFilter::Error,
});
} else {
// Consume map of directives.
let directives_map = mem::take(&mut self.directives);
directives = directives_map
.into_iter()
.map(|(name, level)| Directive { name, level })
.collect();
// Consume directives.
directives = mem::take(&mut self.directives);
// Sort the directives by length of their name, this allows a
// little more efficient lookup at runtime.
directives.sort_by(|a, b| {
Expand Down