Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 42 additions & 7 deletions profiling/src/profiling/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,7 @@ pub enum UploadMessage {
}

const COW_EVAL: Cow<str> = Cow::Borrowed("[eval]");
const COW_PROFILER_STACK_WALK: Cow<str> = Cow::Borrowed("[profiler stack walk]");

const DDPROF_TIME: &str = "ddprof_time";
const DDPROF_UPLOAD: &str = "ddprof_upload";
Expand Down Expand Up @@ -908,12 +909,10 @@ impl Profiler {
pub fn collect_time(&self, execute_data: *mut zend_execute_data, interrupt_count: u32) {
// todo: should probably exclude the wall and CPU time used by collecting the sample.
let interrupt_count = interrupt_count as i64;
let result = collect_stack_sample(execute_data);
let (result, wall_time, cpu_time) = self.collect_stack_sample_with_timeline(execute_data);
match result {
Ok(frames) => {
let depth = frames.len();
let (wall_time, cpu_time) = CLOCKS.with_borrow_mut(Clocks::rotate_clocks);

let labels = Profiler::common_labels(0);
let n_labels = labels.len();

Expand Down Expand Up @@ -956,15 +955,14 @@ impl Profiler {
alloc_size: i64,
interrupt_count: Option<u32>,
) {
let result = collect_stack_sample(execute_data);
let (result, wall_time, cpu_time) = self.collect_stack_sample_with_timeline(execute_data);
match result {
Ok(frames) => {
let depth = frames.len();

// Optionally collect time data when interrupt_count is provided
let (interrupt_count, wall_time, cpu_time, timestamp) =
if let Some(count) = interrupt_count {
let (wall_time, cpu_time) = CLOCKS.with_borrow_mut(Clocks::rotate_clocks);
let timestamp = self.get_timeline_timestamp();
(count as i64, wall_time, cpu_time, timestamp)
} else {
Expand Down Expand Up @@ -1009,7 +1007,7 @@ impl Profiler {
exception: String,
message: Option<String>,
) {
let result = collect_stack_sample(execute_data);
let (result, _wall_time, _cpu_time) = self.collect_stack_sample_with_timeline(execute_data);
match result {
Ok(frames) => {
let depth = frames.len();
Expand Down Expand Up @@ -1409,7 +1407,7 @@ impl Profiler {
where
F: FnOnce(&mut SampleValues),
{
let result = collect_stack_sample(execute_data);
let (result, _wall_time, _cpu_time) = self.collect_stack_sample_with_timeline(execute_data);
match result {
Ok(frames) => {
let depth = frames.len();
Expand Down Expand Up @@ -1543,6 +1541,43 @@ impl Profiler {
},
}
}

fn collect_stack_sample_with_timeline(
&self,
execute_data: *mut zend_execute_data,
) -> (Result<Vec<ZendFrame>, CollectStackSampleError>, i64, i64) {
let (wall_time, cpu_time) = CLOCKS.with_borrow_mut(Clocks::rotate_clocks);
let result = collect_stack_sample(execute_data);
let (stack_walk_wall_time, stack_walk_cpu_time) =
CLOCKS.with_borrow_mut(Clocks::rotate_clocks);

let timestamp = self.get_timeline_timestamp();
let labels = Profiler::common_labels(0);
let n_labels = labels.len();
match self.prepare_and_send_message(
vec![ZendFrame {
function: COW_PROFILER_STACK_WALK,
file: None,
line: 0,
}],
SampleValues {
wall_time: stack_walk_wall_time,
cpu_time: stack_walk_cpu_time,
..Default::default()
},
labels,
timestamp,
) {
Ok(_) => {
trace!("Sent stack walk sample with {n_labels} labels to profiler.")
}
Err(err) => {
warn!("Failed to send stack walk sample with {n_labels} labels to profiler: {err}")
}
}

(result, wall_time, cpu_time)
}
}

pub struct JoinError {
Expand Down
Loading