From e6f32c6d3a5626a1f071d96d2cdebe630abdd5a3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 14 Apr 2019 22:54:57 +0300 Subject: fast path for disabled profiler --- crates/ra_prof/src/lib.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'crates/ra_prof') diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index 1cc8e361d..121a62813 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs @@ -6,7 +6,7 @@ use std::iter::repeat; use std::collections::{HashSet}; use std::default::Default; use std::iter::FromIterator; -use std::sync::RwLock; +use std::sync::{RwLock, atomic::{AtomicBool, Ordering}}; use lazy_static::lazy_static; /// Set profiling filter. It specifies descriptions allowed to profile. @@ -24,6 +24,7 @@ use lazy_static::lazy_static; /// ``` /// pub fn set_filter(f: Filter) { + PROFILING_ENABLED.store(f.depth > 0, Ordering::SeqCst); let set = HashSet::from_iter(f.allowed.iter().cloned()); let mut old = FILTER.write().unwrap(); let filter_data = FilterData { depth: f.depth, allowed: set, version: old.version + 1 }; @@ -62,6 +63,11 @@ pub fn set_filter(f: Filter) { /// ``` /// pub fn profile(desc: &str) -> Profiler { + assert!(!desc.is_empty()); + if !PROFILING_ENABLED.load(Ordering::Relaxed) { + return Profiler { desc: None }; + } + PROFILE_STACK.with(|stack| { let mut stack = stack.borrow_mut(); if stack.starts.len() == 0 { @@ -74,14 +80,14 @@ pub fn profile(desc: &str) -> Profiler { Err(_) => (), }; } - let desc_str = desc.to_string(); - if desc_str.is_empty() { - Profiler { desc: None } - } else if stack.starts.len() < stack.filter_data.depth - && stack.filter_data.allowed.contains(&desc_str) - { + + if stack.starts.len() > stack.filter_data.depth { + return Profiler { desc: None }; + } + + if stack.filter_data.allowed.is_empty() || stack.filter_data.allowed.contains(desc) { stack.starts.push(Instant::now()); - Profiler { desc: Some(desc_str) } + Profiler { desc: Some(desc.to_string()) } } else { Profiler { desc: None } } @@ -128,6 +134,8 @@ struct FilterData { allowed: HashSet, } +static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false); + lazy_static! { static ref FILTER: RwLock = RwLock::new(Default::default()); } -- cgit v1.2.3 From b228947b6863f5864b48bb3a7f3dcca921f58d0b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 14 Apr 2019 23:04:08 +0300 Subject: cleanup syntax --- crates/ra_prof/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'crates/ra_prof') diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index 121a62813..c7c21b6d2 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs @@ -104,6 +104,10 @@ pub struct Filter { } impl Filter { + pub fn disabled() -> Filter { + Filter::new(0, Vec::new()) + } + pub fn new(depth: usize, allowed: Vec) -> Filter { Filter { depth, allowed } } -- cgit v1.2.3 From 5b7012318cdf5fb0bb8b01319270c1b4bf0311ee Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 14 Apr 2019 23:18:58 +0300 Subject: filter by time --- crates/ra_prof/src/lib.rs | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) (limited to 'crates/ra_prof') diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index c7c21b6d2..999cc61f0 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs @@ -27,7 +27,8 @@ pub fn set_filter(f: Filter) { PROFILING_ENABLED.store(f.depth > 0, Ordering::SeqCst); let set = HashSet::from_iter(f.allowed.iter().cloned()); let mut old = FILTER.write().unwrap(); - let filter_data = FilterData { depth: f.depth, allowed: set, version: old.version + 1 }; + let filter_data = + FilterData { depth: f.depth, allowed: set, cutoff: f.cutoff, version: old.version + 1 }; *old = filter_data; } @@ -101,15 +102,41 @@ pub struct Profiler { pub struct Filter { depth: usize, allowed: Vec, + cutoff: Duration, } impl Filter { + // Filtering syntax + // env RA_PROFILE=* // dump everything + // env RA_PROFILE=foo|bar|baz // enabled only selected entries + // env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms + pub fn from_spec(mut spec: &str) -> Filter { + let cutoff = if let Some(idx) = spec.rfind(">") { + let cutoff = spec[idx + 1..].parse().expect("invalid profile cutoff"); + spec = &spec[..idx]; + Duration::from_millis(cutoff) + } else { + Duration::new(0, 0) + }; + + let depth = if let Some(idx) = spec.rfind("@") { + let depth: usize = spec[idx + 1..].parse().expect("invalid profile depth"); + spec = &spec[..idx]; + depth + } else { + 999 + }; + let allowed = + if spec == "*" { Vec::new() } else { spec.split("|").map(String::from).collect() }; + Filter::new(depth, allowed, cutoff) + } + pub fn disabled() -> Filter { - Filter::new(0, Vec::new()) + Filter::new(0, Vec::new(), Duration::new(0, 0)) } - pub fn new(depth: usize, allowed: Vec) -> Filter { - Filter { depth, allowed } + pub fn new(depth: usize, allowed: Vec, cutoff: Duration) -> Filter { + Filter { depth, allowed, cutoff } } } @@ -136,6 +163,7 @@ struct FilterData { depth: usize, version: usize, allowed: HashSet, + cutoff: Duration, } static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false); @@ -159,7 +187,9 @@ impl Drop for Profiler { stack.messages.push(Message { level, duration, message }); if level == 0 { let stdout = stderr(); - print(0, &stack.messages, &mut stdout.lock()); + if duration >= stack.filter_data.cutoff { + print(0, &stack.messages, &mut stdout.lock()); + } stack.messages.clear(); } }); -- cgit v1.2.3 From 06615bd331791a21cfd2e262c5c08949ac9b495b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 14 Apr 2019 23:20:12 +0300 Subject: more intuitive name --- crates/ra_prof/src/lib.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'crates/ra_prof') diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index 999cc61f0..1fac0b14a 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs @@ -27,8 +27,12 @@ pub fn set_filter(f: Filter) { PROFILING_ENABLED.store(f.depth > 0, Ordering::SeqCst); let set = HashSet::from_iter(f.allowed.iter().cloned()); let mut old = FILTER.write().unwrap(); - let filter_data = - FilterData { depth: f.depth, allowed: set, cutoff: f.cutoff, version: old.version + 1 }; + let filter_data = FilterData { + depth: f.depth, + allowed: set, + longer_than: f.longer_than, + version: old.version + 1, + }; *old = filter_data; } @@ -102,7 +106,7 @@ pub struct Profiler { pub struct Filter { depth: usize, allowed: Vec, - cutoff: Duration, + longer_than: Duration, } impl Filter { @@ -111,10 +115,10 @@ impl Filter { // env RA_PROFILE=foo|bar|baz // enabled only selected entries // env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms pub fn from_spec(mut spec: &str) -> Filter { - let cutoff = if let Some(idx) = spec.rfind(">") { - let cutoff = spec[idx + 1..].parse().expect("invalid profile cutoff"); + let longer_than = if let Some(idx) = spec.rfind(">") { + let longer_than = spec[idx + 1..].parse().expect("invalid profile longer_than"); spec = &spec[..idx]; - Duration::from_millis(cutoff) + Duration::from_millis(longer_than) } else { Duration::new(0, 0) }; @@ -128,15 +132,15 @@ impl Filter { }; let allowed = if spec == "*" { Vec::new() } else { spec.split("|").map(String::from).collect() }; - Filter::new(depth, allowed, cutoff) + Filter::new(depth, allowed, longer_than) } pub fn disabled() -> Filter { Filter::new(0, Vec::new(), Duration::new(0, 0)) } - pub fn new(depth: usize, allowed: Vec, cutoff: Duration) -> Filter { - Filter { depth, allowed, cutoff } + pub fn new(depth: usize, allowed: Vec, longer_than: Duration) -> Filter { + Filter { depth, allowed, longer_than } } } @@ -163,7 +167,7 @@ struct FilterData { depth: usize, version: usize, allowed: HashSet, - cutoff: Duration, + longer_than: Duration, } static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false); @@ -187,7 +191,7 @@ impl Drop for Profiler { stack.messages.push(Message { level, duration, message }); if level == 0 { let stdout = stderr(); - if duration >= stack.filter_data.cutoff { + if duration >= stack.filter_data.longer_than { print(0, &stack.messages, &mut stdout.lock()); } stack.messages.clear(); -- cgit v1.2.3 From 247ac265f1e7f2d812e6f9174d48ceef45465b91 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 15 Apr 2019 01:03:11 +0300 Subject: fix test --- crates/ra_prof/src/lib.rs | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'crates/ra_prof') diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index 1fac0b14a..402c719b1 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs @@ -15,14 +15,10 @@ use lazy_static::lazy_static; /// /// #Example /// ``` -/// use ra_prof::set_filter; -/// use ra_prof::Filter; -/// let max_depth = 2; -/// let allowed = vec!["profile1".to_string(), "profile2".to_string()]; -/// let f = Filter::new( max_depth, allowed ); +/// use ra_prof::{set_filter, Filter}; +/// let f = Filter::from_spec("profile1|profile2@2"); /// set_filter(f); /// ``` -/// pub fn set_filter(f: Filter) { PROFILING_ENABLED.store(f.depth > 0, Ordering::SeqCst); let set = HashSet::from_iter(f.allowed.iter().cloned()); @@ -43,12 +39,9 @@ pub fn set_filter(f: Filter) { /// /// #Example /// ``` -/// use ra_prof::profile; -/// use ra_prof::set_filter; -/// use ra_prof::Filter; +/// use ra_prof::{profile, set_filter, Filter}; /// -/// let allowed = vec!["profile1".to_string(), "profile2".to_string()]; -/// let f = Filter::new(2, allowed); +/// let f = Filter::from_spec("profile1|profile2@2"); /// set_filter(f); /// profiling_function1(); /// @@ -66,7 +59,6 @@ pub fn set_filter(f: Filter) { /// 0ms - profile /// 0ms - profile2 /// ``` -/// pub fn profile(desc: &str) -> Profiler { assert!(!desc.is_empty()); if !PROFILING_ENABLED.load(Ordering::Relaxed) { @@ -220,15 +212,12 @@ fn print(lvl: usize, msgs: &[Message], out: &mut impl Write) { #[cfg(test)] mod tests { - - use super::profile; - use super::set_filter; - use super::Filter; + use super::*; #[test] fn test_basic_profile() { let s = vec!["profile1".to_string(), "profile2".to_string()]; - let f = Filter::new(2, s); + let f = Filter::new(2, s, Duration::new(0, 0)); set_filter(f); profiling_function1(); } -- cgit v1.2.3