From b3e9f3d143b0fae970449b7c49a2daf6f966a068 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 25 Apr 2020 15:02:09 +0200 Subject: Move hprof to a separate file --- crates/ra_prof/src/lib.rs | 400 +--------------------------------------------- 1 file changed, 7 insertions(+), 393 deletions(-) (limited to 'crates/ra_prof/src/lib.rs') diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index d95ad3107..e6d672ef5 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs @@ -1,24 +1,16 @@ -//! FIXME: write short doc here +//! A collection of tools for profiling rust-analyzer. mod memory_usage; #[cfg(feature = "cpu_profiler")] mod google_cpu_profiler; +mod hprof; -use std::{ - cell::RefCell, - collections::BTreeMap, - collections::HashSet, - io::{stderr, Write}, - sync::{ - atomic::{AtomicBool, Ordering}, - RwLock, - }, - time::{Duration, Instant}, -}; - -use once_cell::sync::Lazy; +use std::cell::RefCell; -pub use crate::memory_usage::{Bytes, MemoryUsage}; +pub use crate::{ + hprof::{init, init_from, profile}, + memory_usage::{Bytes, MemoryUsage}, +}; // We use jemalloc mainly to get heap usage statistics, actual performance // difference is not measures. @@ -26,301 +18,6 @@ pub use crate::memory_usage::{Bytes, MemoryUsage}; #[global_allocator] static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; -/// 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 init() { - let spec = std::env::var("RA_PROFILE").unwrap_or_default(); - init_from(&spec); -} - -pub fn init_from(spec: &str) { - let filter = if spec.is_empty() { Filter::disabled() } else { Filter::from_spec(spec) }; - set_filter(filter); -} - -/// Set profiling filter. It specifies descriptions allowed to profile. -/// This is helpful when call stack has too many nested profiling scopes. -/// Additionally filter can specify maximum depth of profiling scopes nesting. -/// -/// #Example -/// ``` -/// use ra_prof::{set_filter, Filter}; -/// let f = Filter::from_spec("profile1|profile2@2"); -/// set_filter(f); -/// ``` -fn set_filter(f: Filter) { - PROFILING_ENABLED.store(f.depth > 0, Ordering::SeqCst); - let set: HashSet<_> = f.allowed.iter().cloned().collect(); - let mut old = FILTER.write().unwrap(); - let filter_data = FilterData { - depth: f.depth, - allowed: set, - longer_than: f.longer_than, - version: old.version + 1, - }; - *old = filter_data; -} - -pub type Label = &'static str; - -/// This function starts a profiling scope in the current execution stack with a given description. -/// It returns a Profile structure and measure elapsed time between this method invocation and Profile structure drop. -/// It supports nested profiling scopes in case when this function invoked multiple times at the execution stack. In this case the profiling information will be nested at the output. -/// Profiling information is being printed in the stderr. -/// -/// # Example -/// ``` -/// use ra_prof::{profile, set_filter, Filter}; -/// -/// let f = Filter::from_spec("profile1|profile2@2"); -/// set_filter(f); -/// profiling_function1(); -/// -/// fn profiling_function1() { -/// let _p = profile("profile1"); -/// profiling_function2(); -/// } -/// -/// fn profiling_function2() { -/// let _p = profile("profile2"); -/// } -/// ``` -/// This will print in the stderr the following: -/// ```text -/// 0ms - profile -/// 0ms - profile2 -/// ``` -pub fn profile(label: Label) -> Profiler { - assert!(!label.is_empty()); - if !PROFILING_ENABLED.load(Ordering::Relaxed) { - return Profiler { label: None, detail: None }; - } - - PROFILE_STACK.with(|stack| { - let mut stack = stack.borrow_mut(); - if stack.starts.is_empty() { - if let Ok(f) = FILTER.try_read() { - if f.version > stack.filter_data.version { - stack.filter_data = f.clone(); - } - }; - } - if stack.starts.len() > stack.filter_data.depth { - return Profiler { label: None, detail: None }; - } - let allowed = &stack.filter_data.allowed; - if stack.starts.is_empty() && !allowed.is_empty() && !allowed.contains(label) { - return Profiler { label: None, detail: None }; - } - - stack.starts.push(Instant::now()); - Profiler { label: Some(label), detail: None } - }) -} - -pub struct Profiler { - label: Option