Allow specifying additional info on call to profile
This commit is contained in:
parent
59f91f2f9b
commit
b33b843f40
3 changed files with 52 additions and 21 deletions
|
@ -16,6 +16,7 @@ use crate::{
|
||||||
Binders, CallableDef, GenericPredicate, InferenceResult, PolyFnSig, Substs, TraitRef, Ty,
|
Binders, CallableDef, GenericPredicate, InferenceResult, PolyFnSig, Substs, TraitRef, Ty,
|
||||||
TyDefId, TypeCtor, ValueTyDefId,
|
TyDefId, TypeCtor, ValueTyDefId,
|
||||||
};
|
};
|
||||||
|
use hir_expand::name::Name;
|
||||||
|
|
||||||
#[salsa::query_group(HirDatabaseStorage)]
|
#[salsa::query_group(HirDatabaseStorage)]
|
||||||
#[salsa::requires(salsa::Database)]
|
#[salsa::requires(salsa::Database)]
|
||||||
|
@ -111,7 +112,15 @@ pub trait HirDatabase: DefDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
|
fn infer(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
|
||||||
let _p = profile("wait_infer");
|
let _p = profile("wait_infer").detail(|| match def {
|
||||||
|
DefWithBodyId::FunctionId(it) => db.function_data(it).name.to_string(),
|
||||||
|
DefWithBodyId::StaticId(it) => {
|
||||||
|
db.static_data(it).name.clone().unwrap_or_else(Name::missing).to_string()
|
||||||
|
}
|
||||||
|
DefWithBodyId::ConstId(it) => {
|
||||||
|
db.const_data(it).name.clone().unwrap_or_else(Name::missing).to_string()
|
||||||
|
}
|
||||||
|
});
|
||||||
db.do_infer(def)
|
db.do_infer(def)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,10 @@ pub(crate) fn trait_solve_query(
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
goal: Canonical<InEnvironment<Obligation>>,
|
goal: Canonical<InEnvironment<Obligation>>,
|
||||||
) -> Option<Solution> {
|
) -> Option<Solution> {
|
||||||
let _p = profile("trait_solve_query");
|
let _p = profile("trait_solve_query").detail(|| match &goal.value.value {
|
||||||
|
Obligation::Trait(it) => db.trait_data(it.trait_).name.to_string(),
|
||||||
|
Obligation::Projection(_) => "projection".to_string(),
|
||||||
|
});
|
||||||
log::debug!("trait_solve_query({})", goal.value.value.display(db));
|
log::debug!("trait_solve_query({})", goal.value.value.display(db));
|
||||||
|
|
||||||
if let Obligation::Projection(pred) = &goal.value.value {
|
if let Obligation::Projection(pred) = &goal.value.value {
|
||||||
|
|
|
@ -88,7 +88,7 @@ pub type Label = &'static str;
|
||||||
pub fn profile(label: Label) -> Profiler {
|
pub fn profile(label: Label) -> Profiler {
|
||||||
assert!(!label.is_empty());
|
assert!(!label.is_empty());
|
||||||
if !PROFILING_ENABLED.load(Ordering::Relaxed) {
|
if !PROFILING_ENABLED.load(Ordering::Relaxed) {
|
||||||
return Profiler { label: None };
|
return Profiler { label: None, detail: None };
|
||||||
}
|
}
|
||||||
|
|
||||||
PROFILE_STACK.with(|stack| {
|
PROFILE_STACK.with(|stack| {
|
||||||
|
@ -101,15 +101,15 @@ pub fn profile(label: Label) -> Profiler {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if stack.starts.len() > stack.filter_data.depth {
|
if stack.starts.len() > stack.filter_data.depth {
|
||||||
return Profiler { label: None };
|
return Profiler { label: None, detail: None };
|
||||||
}
|
}
|
||||||
let allowed = &stack.filter_data.allowed;
|
let allowed = &stack.filter_data.allowed;
|
||||||
if stack.starts.is_empty() && !allowed.is_empty() && !allowed.contains(label) {
|
if stack.starts.is_empty() && !allowed.is_empty() && !allowed.contains(label) {
|
||||||
return Profiler { label: None };
|
return Profiler { label: None, detail: None };
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.starts.push(Instant::now());
|
stack.starts.push(Instant::now());
|
||||||
Profiler { label: Some(label) }
|
Profiler { label: Some(label), detail: None }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +130,16 @@ pub fn print_time(label: Label) -> impl Drop {
|
||||||
|
|
||||||
pub struct Profiler {
|
pub struct Profiler {
|
||||||
label: Option<Label>,
|
label: Option<Label>,
|
||||||
|
detail: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Profiler {
|
||||||
|
pub fn detail(mut self, detail: impl FnOnce() -> String) -> Profiler {
|
||||||
|
if self.label.is_some() {
|
||||||
|
self.detail = Some(detail())
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Filter {
|
pub struct Filter {
|
||||||
|
@ -183,6 +193,7 @@ struct Message {
|
||||||
level: usize,
|
level: usize,
|
||||||
duration: Duration,
|
duration: Duration,
|
||||||
label: Label,
|
label: Label,
|
||||||
|
detail: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProfileStack {
|
impl ProfileStack {
|
||||||
|
@ -208,13 +219,13 @@ thread_local!(static PROFILE_STACK: RefCell<ProfileStack> = RefCell::new(Profile
|
||||||
impl Drop for Profiler {
|
impl Drop for Profiler {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
match self {
|
match self {
|
||||||
Profiler { label: Some(label) } => {
|
Profiler { label: Some(label), detail } => {
|
||||||
PROFILE_STACK.with(|stack| {
|
PROFILE_STACK.with(|stack| {
|
||||||
let mut stack = stack.borrow_mut();
|
let mut stack = stack.borrow_mut();
|
||||||
let start = stack.starts.pop().unwrap();
|
let start = stack.starts.pop().unwrap();
|
||||||
let duration = start.elapsed();
|
let duration = start.elapsed();
|
||||||
let level = stack.starts.len();
|
let level = stack.starts.len();
|
||||||
stack.messages.push(Message { level, duration, label });
|
stack.messages.push(Message { level, duration, label, detail: detail.take() });
|
||||||
if level == 0 {
|
if level == 0 {
|
||||||
let stdout = stderr();
|
let stdout = stderr();
|
||||||
let longer_than = stack.filter_data.longer_than;
|
let longer_than = stack.filter_data.longer_than;
|
||||||
|
@ -228,7 +239,7 @@ impl Drop for Profiler {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Profiler { label: None } => (),
|
Profiler { label: None, .. } => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,8 +262,16 @@ fn print_for_idx(
|
||||||
) {
|
) {
|
||||||
let current = &msgs[current_idx];
|
let current = &msgs[current_idx];
|
||||||
let current_indent = " ".repeat(current.level);
|
let current_indent = " ".repeat(current.level);
|
||||||
writeln!(out, "{}{:5}ms - {}", current_indent, current.duration.as_millis(), current.label)
|
let detail = current.detail.as_ref().map(|it| format!(" @ {}", it)).unwrap_or_default();
|
||||||
.expect("printing profiling info");
|
writeln!(
|
||||||
|
out,
|
||||||
|
"{}{:5}ms - {}{}",
|
||||||
|
current_indent,
|
||||||
|
current.duration.as_millis(),
|
||||||
|
current.label,
|
||||||
|
detail,
|
||||||
|
)
|
||||||
|
.expect("printing profiling info");
|
||||||
|
|
||||||
let longer_than_millis = longer_than.as_millis();
|
let longer_than_millis = longer_than.as_millis();
|
||||||
let children_indices = &children_map[current_idx];
|
let children_indices = &children_map[current_idx];
|
||||||
|
@ -417,9 +436,9 @@ mod tests {
|
||||||
fn test_longer_than() {
|
fn test_longer_than() {
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let msgs = vec![
|
let msgs = vec![
|
||||||
Message { level: 1, duration: Duration::from_nanos(3), label: "bar" },
|
Message { level: 1, duration: Duration::from_nanos(3), label: "bar", detail: None },
|
||||||
Message { level: 1, duration: Duration::from_nanos(2), label: "bar" },
|
Message { level: 1, duration: Duration::from_nanos(2), label: "bar", detail: None },
|
||||||
Message { level: 0, duration: Duration::from_millis(1), label: "foo" },
|
Message { level: 0, duration: Duration::from_millis(1), label: "foo", detail: None },
|
||||||
];
|
];
|
||||||
print(&msgs, Duration::from_millis(0), &mut result);
|
print(&msgs, Duration::from_millis(0), &mut result);
|
||||||
// The calls to `bar` are so short that they'll be rounded to 0ms and should get collapsed
|
// The calls to `bar` are so short that they'll be rounded to 0ms and should get collapsed
|
||||||
|
@ -434,8 +453,8 @@ mod tests {
|
||||||
fn test_unaccounted_for_topmost() {
|
fn test_unaccounted_for_topmost() {
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let msgs = vec![
|
let msgs = vec![
|
||||||
Message { level: 1, duration: Duration::from_millis(2), label: "bar" },
|
Message { level: 1, duration: Duration::from_millis(2), label: "bar", detail: None },
|
||||||
Message { level: 0, duration: Duration::from_millis(5), label: "foo" },
|
Message { level: 0, duration: Duration::from_millis(5), label: "foo", detail: None },
|
||||||
];
|
];
|
||||||
print(&msgs, Duration::from_millis(0), &mut result);
|
print(&msgs, Duration::from_millis(0), &mut result);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -453,11 +472,11 @@ mod tests {
|
||||||
fn test_unaccounted_for_multiple_levels() {
|
fn test_unaccounted_for_multiple_levels() {
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let msgs = vec![
|
let msgs = vec![
|
||||||
Message { level: 2, duration: Duration::from_millis(3), label: "baz" },
|
Message { level: 2, duration: Duration::from_millis(3), label: "baz", detail: None },
|
||||||
Message { level: 1, duration: Duration::from_millis(5), label: "bar" },
|
Message { level: 1, duration: Duration::from_millis(5), label: "bar", detail: None },
|
||||||
Message { level: 2, duration: Duration::from_millis(2), label: "baz" },
|
Message { level: 2, duration: Duration::from_millis(2), label: "baz", detail: None },
|
||||||
Message { level: 1, duration: Duration::from_millis(4), label: "bar" },
|
Message { level: 1, duration: Duration::from_millis(4), label: "bar", detail: None },
|
||||||
Message { level: 0, duration: Duration::from_millis(9), label: "foo" },
|
Message { level: 0, duration: Duration::from_millis(9), label: "foo", detail: None },
|
||||||
];
|
];
|
||||||
print(&msgs, Duration::from_millis(0), &mut result);
|
print(&msgs, Duration::from_millis(0), &mut result);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Add table
Reference in a new issue