Skip to content

Commit 9a4063c

Browse files
perf(profiling): fast-path bypass on non-PHP threads for all IO hooks
1 parent 089e39a commit 9a4063c

1 file changed

Lines changed: 45 additions & 9 deletions

File tree

profiling/src/io/mod.rs

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ pub struct GotSymbolOverwrite {
5757
pub new_func: *mut (),
5858
}
5959

60+
#[inline]
61+
fn is_zend_thread() -> bool {
62+
REQUEST_LOCALS.borrow_or_false(|locals| !locals.vm_interrupt_addr.is_null())
63+
}
64+
6065
fn eval_poll_events(ret: i32, fds: &[libc::pollfd]) -> (bool, bool) {
6166
let mut has_read = false;
6267
let mut has_write = false;
@@ -96,6 +101,10 @@ unsafe extern "C" fn observed_poll(
96101
nfds: libc::nfds_t,
97102
timeout: c_int,
98103
) -> i32 {
104+
if !is_zend_thread() {
105+
return libc::poll(fds, nfds, timeout);
106+
}
107+
99108
let start = Instant::now();
100109
let ret = libc::poll(fds, nfds, timeout);
101110
let _errno_backup = ErrnoBackup::new();
@@ -129,6 +138,10 @@ unsafe extern "C" fn observed_recv(
129138
length: usize,
130139
flags: c_int,
131140
) -> isize {
141+
if !is_zend_thread() {
142+
return libc::recv(socket, buf, length, flags);
143+
}
144+
132145
let start = Instant::now();
133146
let len = libc::recv(socket, buf, length, flags);
134147
let _errno_backup = ErrnoBackup::new();
@@ -154,6 +167,10 @@ unsafe extern "C" fn observed_recvmsg(
154167
msg: *mut libc::msghdr,
155168
flags: c_int,
156169
) -> isize {
170+
if !is_zend_thread() {
171+
return libc::recvmsg(socket, msg, flags);
172+
}
173+
157174
let start = Instant::now();
158175
let len = libc::recvmsg(socket, msg, flags);
159176
let _errno_backup = ErrnoBackup::new();
@@ -182,6 +199,10 @@ unsafe extern "C" fn observed_recvfrom(
182199
address: *mut libc::sockaddr,
183200
address_len: *mut libc::socklen_t,
184201
) -> isize {
202+
if !is_zend_thread() {
203+
return libc::recvfrom(socket, buf, length, flags, address, address_len);
204+
}
205+
185206
let start = Instant::now();
186207
let len = libc::recvfrom(socket, buf, length, flags, address, address_len);
187208
let _errno_backup = ErrnoBackup::new();
@@ -208,6 +229,10 @@ unsafe extern "C" fn observed_send(
208229
length: usize,
209230
flags: c_int,
210231
) -> isize {
232+
if !is_zend_thread() {
233+
return libc::send(socket, buf, length, flags);
234+
}
235+
211236
let start = Instant::now();
212237
let len = libc::send(socket, buf, length, flags);
213238
let _errno_backup = ErrnoBackup::new();
@@ -233,6 +258,10 @@ unsafe extern "C" fn observed_sendmsg(
233258
msg: *const libc::msghdr,
234259
flags: c_int,
235260
) -> isize {
261+
if !is_zend_thread() {
262+
return libc::sendmsg(socket, msg, flags);
263+
}
264+
236265
let start = Instant::now();
237266
let len = libc::sendmsg(socket, msg, flags);
238267
let _errno_backup = ErrnoBackup::new();
@@ -259,6 +288,10 @@ unsafe extern "C" fn observed_fwrite(
259288
nobj: usize,
260289
stream: *mut libc::FILE,
261290
) -> usize {
291+
if !is_zend_thread() {
292+
return libc::fwrite(ptr, size, nobj, stream);
293+
}
294+
262295
let start = Instant::now();
263296
let len = libc::fwrite(ptr, size, nobj, stream);
264297
let _errno_backup = ErrnoBackup::new();
@@ -279,6 +312,10 @@ unsafe extern "C" fn observed_fwrite(
279312
}
280313

281314
unsafe extern "C" fn observed_write(fd: c_int, buf: *const c_void, count: usize) -> isize {
315+
if !is_zend_thread() {
316+
return libc::write(fd, buf, count);
317+
}
318+
282319
let start = Instant::now();
283320
let len = libc::write(fd, buf, count);
284321
let _errno_backup = ErrnoBackup::new();
@@ -326,6 +363,10 @@ unsafe extern "C" fn observed_fread(
326363
nobj: usize,
327364
stream: *mut libc::FILE,
328365
) -> usize {
366+
if !is_zend_thread() {
367+
return libc::fread(ptr, size, nobj, stream);
368+
}
369+
329370
let start = Instant::now();
330371
let len = libc::fread(ptr, size, nobj, stream);
331372
let _errno_backup = ErrnoBackup::new();
@@ -346,6 +387,10 @@ unsafe extern "C" fn observed_fread(
346387
}
347388

348389
unsafe extern "C" fn observed_read(fd: c_int, buf: *mut c_void, count: usize) -> isize {
390+
if !is_zend_thread() {
391+
return libc::read(fd, buf, count);
392+
}
393+
349394
let start = Instant::now();
350395
let len = libc::read(fd, buf, count);
351396
let _errno_backup = ErrnoBackup::new();
@@ -563,15 +608,6 @@ impl IOProfilingStats {
563608
}
564609

565610
fn should_collect(&mut self, value: u64) -> bool {
566-
let zend_thread =
567-
REQUEST_LOCALS.borrow_or_false(|locals| !locals.vm_interrupt_addr.is_null());
568-
if !zend_thread {
569-
// `curl_exec()` for example will spawn a new thread for name resolution. GOT hooking
570-
// follows threads and as such we might sample from another (non PHP) thread even in a
571-
// NTS build of PHP. We have observed crashes for these cases, so instead of crashing
572-
// (or risking a crash) we refrain from collection I/O.
573-
return false;
574-
}
575611
if let Some(next_sample) = self.next_sample.checked_sub(value) {
576612
self.next_sample = next_sample;
577613
return false;

0 commit comments

Comments
 (0)