-
-
Notifications
You must be signed in to change notification settings - Fork 145
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
feat(subscriber): support multiple task callsites #68
Changes from all commits
70ac0ba
eba8c00
c3cdc48
3b8373a
0bbaac5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,53 @@ | ||||||
use std::{ | ||||||
ptr, | ||||||
sync::atomic::{AtomicPtr, AtomicUsize, Ordering}, | ||||||
}; | ||||||
use tracing_core::Metadata; | ||||||
|
||||||
#[derive(Debug, Default)] | ||||||
pub(crate) struct Callsites { | ||||||
ptrs: [AtomicPtr<Metadata<'static>>; MAX_CALLSITES], | ||||||
len: AtomicUsize, | ||||||
} | ||||||
|
||||||
// In practice each of these will have like, 1-5 callsites in it, max, so | ||||||
// 32 is probably fine...if it ever becomes not fine, we'll fix that. | ||||||
const MAX_CALLSITES: usize = 32; | ||||||
|
||||||
impl Callsites { | ||||||
#[track_caller] | ||||||
pub(crate) fn insert(&self, callsite: &'static Metadata<'static>) { | ||||||
// The callsite may already have been inserted, if the callsite cache | ||||||
// was invalidated and is being rebuilt. In that case, don't insert it | ||||||
// again.' | ||||||
if self.contains(callsite) { | ||||||
return; | ||||||
} | ||||||
|
||||||
let idx = self.len.fetch_add(1, Ordering::AcqRel); | ||||||
assert!( | ||||||
idx < MAX_CALLSITES, | ||||||
"you tried to store more than 64 callsites, \ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This still says 64 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. whoops lol
Suggested change
|
||||||
time to make the callsite sets bigger i guess \ | ||||||
(please open an issue for this)" | ||||||
); | ||||||
self.ptrs[idx] | ||||||
.compare_exchange( | ||||||
ptr::null_mut(), | ||||||
callsite as *const _ as *mut _, | ||||||
Ordering::AcqRel, | ||||||
Ordering::Acquire, | ||||||
) | ||||||
.expect("a callsite would have been clobbered by `insert` (this is a bug)"); | ||||||
} | ||||||
|
||||||
pub(crate) fn contains(&self, callsite: &'static Metadata<'static>) -> bool { | ||||||
let len = self.len.load(Ordering::Acquire); | ||||||
for cs in &self.ptrs[..len] { | ||||||
if ptr::eq(cs.load(Ordering::Acquire), callsite) { | ||||||
return true; | ||||||
} | ||||||
} | ||||||
false | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,8 +20,9 @@ pub(crate) struct List { | |
} | ||
|
||
impl List { | ||
const HEADER: &'static [&'static str] = | ||
&["TID", "KIND", "TOTAL", "BUSY", "IDLE", "POLLS", "FIELDS"]; | ||
const HEADER: &'static [&'static str] = &[ | ||
"TID", "KIND", "TOTAL", "BUSY", "IDLE", "POLLS", "TARGET", "FIELDS", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the target useful when the fields are showing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, Also, we don't currently require any particular fields from the runtime providing the task spans...so just because Tokio currently provides a |
||
]; | ||
|
||
pub(crate) fn update_input(&mut self, event: input::Event) { | ||
// Clippy likes to remind us that we could use an `if let` here, since | ||
|
@@ -83,6 +84,7 @@ impl List { | |
// there's room for the unit!) | ||
const DUR_PRECISION: usize = 4; | ||
const POLLS_LEN: usize = 5; | ||
const MIN_TARGET_LEN: usize = 15; | ||
|
||
self.sorted_tasks.extend(state.take_new_tasks()); | ||
self.sort_by.sort(now, &mut self.sorted_tasks); | ||
|
@@ -115,6 +117,7 @@ impl List { | |
prec = DUR_PRECISION, | ||
)), | ||
Cell::from(format!("{:>width$}", task.total_polls(), width = POLLS_LEN)), | ||
Cell::from(task.target().to_owned()), | ||
Cell::from(Spans::from( | ||
task.formatted_fields() | ||
.iter() | ||
|
@@ -169,6 +172,7 @@ impl List { | |
layout::Constraint::Min(DUR_LEN as u16), | ||
layout::Constraint::Min(DUR_LEN as u16), | ||
layout::Constraint::Min(POLLS_LEN as u16), | ||
layout::Constraint::Min(MIN_TARGET_LEN as u16), | ||
layout::Constraint::Min(10), | ||
]) | ||
.highlight_symbol(">> ") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder, is the plan to use this structure for tracking other more granular callsites such as resource, resource ops? If that is the case, the number can grow to a value larger than 1 - 5. Is the plan to switch to a map based approach then or would a linear scan still be fast enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking we'd solve that problem when it becomes necessary :)
I think we may just want to use a hashset (or something) for callsites we expect to see a lot of, and arrays for callsites we expect there to be fewer of --- we could come up with some kind of adaptive structure that switches dynamically once it reaches a certain length, but in this case, I think we can make pretty good guesses about which callsites we expect to see a lot of, and which we expect to see fewer of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, as we start caring about more types of callsites, I think we may want to switch to a model where we store the callsite alongside some data about which type of callsite it is, in one array, instead of storing each type of callsites in separate arrays. That way, we only do one linear scan, and then know everything we need to about that callsite, instead of having to look in multiple arrays.