mirror of
https://github.com/php/php-src.git
synced 2026-10-28 09:46:46 +08:00
Implement perf stat --control for cgi (GH-22537)
perf stat --control allows the profiled process to enable and disable counters
at runtime. This allows us to skip profiling startup and shutdown for more
accurate results. The same already exists for valgrind.
$ perf stat -D -1 --control fifo:/tmp/perfctl,/tmp/perfack
-D -1 starts perf stat with counters disabled. --control makes perf stat connect
to the /tmp/perfctl and /tmp/perfack fifo files. These need to exist when
starting perf, so create them using mkfifo /tmp/perf{ctl,ack}. The ctl fifo is
written to by cgi to enable/disable counters, whereas the ack fifo is written to
by perf stat to acknowledge counters have been installed.
Additionally, you'll need to set the set the PERF_STAT_CTL_FIFO and
PERF_STAT_ACK_FIFO env variables for cgi to find the fifo files.
This commit is contained in:
1 parent
9a14b9b070
commit
aae5edb8e3
2 files changed
+146
-2
No files matched your search
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright © Zend Technologies Ltd., a subsidiary company of |
|
||||
| Perforce Software, Inc., and Contributors. |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to the Modified BSD License that is |
|
||||
| bundled with this package in the file LICENSE, and is available |
|
||||
| through the World Wide Web at <https://www.php.net/license/>. |
|
||||
| |
|
||||
| SPDX-License-Identifier: BSD-3-Clause |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Ilija Tovilo <ilutov@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef ZEND_PERF_STAT_H
|
||||
#define ZEND_PERF_STAT_H
|
||||
|
||||
#include "zend_portability.h"
|
||||
|
||||
# if !(HAVE_FCNTL_H && HAVE_SYS_SELECT_H && HAVE_SYS_STAT_H && HAVE_SYS_TIME_H && HAVE_UNISTD_H)
|
||||
static void zend_perf_stat_enable(void) {}
|
||||
static void zend_perf_stat_disable(void) {}
|
||||
# else
|
||||
|
||||
# include <fcntl.h>
|
||||
# include <sys/select.h>
|
||||
# include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
|
||||
# include "Zend/zend.h"
|
||||
|
||||
# define ZPS_CTL_FIFO_ENV "PERF_STAT_CTL_FIFO"
|
||||
# define ZPS_ACK_FIFO_ENV "PERF_STAT_ACK_FIFO"
|
||||
|
||||
static int ctl_fd = -2;
|
||||
static int ack_fd = -2;
|
||||
|
||||
static int zps_open_fifo(const char *env_name, int flags)
|
||||
{
|
||||
const char *path = getenv(env_name);
|
||||
|
||||
if (path == NULL || path[0] == '\0') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
# ifdef O_CLOEXEC
|
||||
flags |= O_CLOEXEC;
|
||||
# endif
|
||||
int fd = open(path, flags | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Failed to open fifo %s\n", path);
|
||||
fflush(stderr);
|
||||
zend_bailout();
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) != 0 || !S_ISFIFO(st.st_mode)) {
|
||||
close(fd);
|
||||
fprintf(stderr, "File %s is not a fifo\n", path);
|
||||
fflush(stderr);
|
||||
zend_bailout();
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void zps_init(void)
|
||||
{
|
||||
if (ctl_fd == -2) {
|
||||
ctl_fd = zps_open_fifo(ZPS_CTL_FIFO_ENV, O_WRONLY);
|
||||
}
|
||||
if (ack_fd == -2) {
|
||||
ack_fd = zps_open_fifo(ZPS_ACK_FIFO_ENV, O_RDONLY);
|
||||
}
|
||||
}
|
||||
|
||||
static void zps_wait_ack(void)
|
||||
{
|
||||
if (ack_fd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
fd_set readfds;
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(ack_fd, &readfds);
|
||||
if (select(ack_fd + 1, &readfds, NULL, NULL, &timeout) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
char ack[sizeof("ack\n") - 1];
|
||||
ssize_t bytes_read;
|
||||
do {
|
||||
bytes_read = read(ack_fd, ack, sizeof(ack));
|
||||
} while (bytes_read > 0);
|
||||
}
|
||||
|
||||
static void zps_control(const char *command, size_t command_len)
|
||||
{
|
||||
zps_init();
|
||||
|
||||
if (ctl_fd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (write(ctl_fd, command, command_len) != (ssize_t) command_len) {
|
||||
close(ctl_fd);
|
||||
ctl_fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
zps_wait_ack();
|
||||
}
|
||||
|
||||
static void zend_perf_stat_enable(void)
|
||||
{
|
||||
static const char command[] = "enable\n";
|
||||
|
||||
zps_control(command, sizeof(command) - 1);
|
||||
}
|
||||
|
||||
static void zend_perf_stat_disable(void)
|
||||
{
|
||||
static const char command[] = "disable\n";
|
||||
|
||||
zps_control(command, sizeof(command) - 1);
|
||||
}
|
||||
|
||||
# endif
|
||||
#endif
|
||||
+11
-2
@@ -95,6 +95,8 @@ int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "zend_perf_stat.h"
|
||||
|
||||
#ifndef PHP_WIN32
|
||||
/* XXX this will need to change later when threaded fastcgi is implemented. shane */
|
||||
static struct sigaction act, old_term, old_quit, old_int;
|
||||
@@ -1733,6 +1735,7 @@ int main(int argc, char *argv[])
|
||||
int warmup_repeats = 0;
|
||||
int repeats = 1;
|
||||
int benchmark = 0;
|
||||
bool perf_enabled = false;
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
struct timeval start, end;
|
||||
#else
|
||||
@@ -2441,14 +2444,16 @@ do_repeat:
|
||||
}
|
||||
} /* end !cgi && !fastcgi */
|
||||
|
||||
#ifdef HAVE_VALGRIND
|
||||
if (warmup_repeats == 0) {
|
||||
zend_perf_stat_enable();
|
||||
perf_enabled = true;
|
||||
#ifdef HAVE_VALGRIND
|
||||
CALLGRIND_START_INSTRUMENTATION;
|
||||
# ifdef HAVE_VALGRIND_CACHEGRIND_H
|
||||
CACHEGRIND_START_INSTRUMENTATION;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* request startup only after we've done all we can to
|
||||
* get path_translated */
|
||||
@@ -2568,6 +2573,10 @@ fastcgi_request_done:
|
||||
SG(request_info).query_string = NULL;
|
||||
}
|
||||
|
||||
if (perf_enabled) {
|
||||
zend_perf_stat_disable();
|
||||
perf_enabled = false;
|
||||
}
|
||||
#ifdef HAVE_VALGRIND
|
||||
/* We're not interested in measuring shutdown */
|
||||
CALLGRIND_STOP_INSTRUMENTATION;
|
||||
|
||||
Reference in new issue
Block a user