perf events: Enable counters when collecting process-wide or system-wide data by 'perf stat'
Subsystems (2)
PATCH 1/3 perf events: Enable counters when collecting process-wide or system-wide data by 'perf stat'
Tool perf has a couple of sub commands. There are a couple of issues around counter enabling time point. In addition, we want a precise time clock when collect system-wide or process/thread-wide statistics.
I worked out 3 patches against tips/master tree of March 17 to fix such issues and enhance perf to be more user-friendly.
Subject: [PATCH 1/3] perf events: Enable counters when collecting process-wide or system-wide data by 'perf stat'
From: Zhang, Yanmin <[email protected]>
Command 'perf stat' doesn't enable counters when collecting an existing (by -p) process or a system-wide statistics. Fix the issue.
Change the condition of fork/exec subcommand. If there is a subcommand parameter, perf always fork/exec it. The usage example is:
#perf stat -a sleep 10
So this command could collect statistics for 10 seconds precisely. User still could stop it by CTRL+C. Without the new capability, user could only use CTRL+C to stop it without precise time clock.
Another issue is 'perf stat -a' consumes 100% time of a full single logical cpu. It has a bad impact on running workload. Fix it by adding a sleep(1) in the while(!done) loop in function run_perf_stat.
---
tools/perf/builtin-stat.c +14 -10
@@ -159,8 +159,10 @@ static void create_perf_stat_counter(int } }else { attr->inherit = inherit; - attr->disabled =1 ; - attr->enable_on_exec =1 ; +if (target_pid ==-1 ) { + attr->disabled =1 ; + attr->enable_on_exec =1 ; + } fd[0 ][counter] =sys_perf_event_open (attr, pid,-1 ,-1 ,0 );if (fd[0 ][counter] <0 && verbose)
@@ -251,9 +253,9 @@ static int run_perf_stat(int argc __usedunsigned long long t0, t1;int status =0 ;int counter; -int pid = target_pid; +int pid;int child_ready_pipe[2 ], go_pipe[2 ]; -const bool forks = (target_pid ==-1 && argc >0 ); +const bool forks = (argc >0 );char buf;if (!system_wide)
@@ -265,10 +267,10 @@ static int run_perf_stat(int argc __used }if (forks) { -if ((pid =fork ()) <0 ) +if ((child_pid =fork ()) <0 )perror ("failed to fork" ); -if (!pid) { +if (!child_pid) {close (child_ready_pipe[0 ]);close (go_pipe[1 ]);fcntl (go_pipe[0 ],F_SETFD ,FD_CLOEXEC );
@@ -297,8 +299,6 @@ static int run_perf_stat(int argc __usedexit (-1 ); } - child_pid = pid; -/* * Wait for the child to be ready to exec. */
@@ -309,6 +309,10 @@ static int run_perf_stat(int argc __usedclose (child_ready_pipe[0 ]); } +if (target_pid ==-1 ) + pid = child_pid; +else + pid = target_pid;for (counter =0 ; counter < nr_counters; counter++)create_perf_stat_counter (counter, pid);
@@ -321,7 +325,7 @@ static int run_perf_stat(int argc __usedclose (go_pipe[1 ]);wait (&status); }else { -while (!done); +while (!done)sleep (1 ); } t1 =rdclock ();
@@ -459,7 +463,7 @@ static volatile int signr = -1;static void skip_signal (int signo) { -if (target_pid !=-1 ) +if (child_pid ==-1 ) done =1 ; signr = signo;