Add a command line argument (-l) to end event collection after some

number of seconds.  The number of seconds may be a fraction.

Submitted by:	Julien Charbon <jcharbon@versign.com>
MFC after:	2 weeks
Relnotes:	yes
This commit is contained in:
gnn 2014-05-16 03:18:09 +00:00
parent 0e1c93d3c1
commit f767e17c96
3 changed files with 51 additions and 3 deletions

View File

@ -52,6 +52,7 @@
.Op Fl f Ar pluginopt
.Op Fl g
.Op Fl k Ar kerneldir
.Op Fl l Ar secs
.Op Fl m Ar pathname
.Op Fl n Ar rate
.Op Fl o Ar outputfile
@ -274,6 +275,13 @@ This directory specifies where
should look for the kernel and its modules.
The default is
.Pa /boot/kernel .
.It Fl l Ar secs
Set system-wide performance measurement duration for
.Ar secs
seconds.
The argument
.Ar secs
may be a fractional value.
.It Fl m Ar pathname
Print the sampled PCs with the name, the start and ending addresses
of the function within they live.

View File

@ -509,6 +509,7 @@ pmcstat_show_usage(void)
"\t -f spec\t pass \"spec\" to as plugin option\n"
"\t -g\t\t produce gprof(1) compatible profiles\n"
"\t -k dir\t\t set the path to the kernel\n"
"\t -l secs\t set duration time\n"
"\t -m file\t print sampled PCs to \"file\"\n"
"\t -n rate\t set sampling rate\n"
"\t -o file\t send print output to \"file\"\n"
@ -551,6 +552,7 @@ main(int argc, char **argv)
{
cpuset_t cpumask;
double interval;
double duration;
int hcpu, option, npmc, ncpu;
int c, check_driver_stats, current_sampling_count;
int do_callchain, do_descendants, do_logproccsw, do_logprocexit;
@ -600,6 +602,7 @@ main(int argc, char **argv)
args.pa_toptty = 0;
args.pa_topcolor = 0;
args.pa_mergepmc = 0;
args.pa_duration = 0.0;
STAILQ_INIT(&args.pa_events);
SLIST_INIT(&args.pa_targets);
bzero(&ds_start, sizeof(ds_start));
@ -618,7 +621,7 @@ main(int argc, char **argv)
CPU_SET(hcpu, &cpumask);
while ((option = getopt(argc, argv,
"CD:EF:G:M:NO:P:R:S:TWa:c:df:gk:m:n:o:p:qr:s:t:vw:z:")) != -1)
"CD:EF:G:M:NO:P:R:S:TWa:c:df:gk:l:m:n:o:p:qr:s:t:vw:z:")) != -1)
switch (option) {
case 'a': /* Annotate + callgraph */
args.pa_flags |= FLAG_DO_ANNOTATE;
@ -692,6 +695,15 @@ main(int argc, char **argv)
args.pa_flags |= FLAG_HAS_KERNELPATH;
break;
case 'l': /* time duration in seconds */
duration = strtod(optarg, &end);
if (*end != '\0' || duration <= 0)
errx(EX_USAGE, "ERROR: Illegal duration time "
"value \"%s\".", optarg);
args.pa_flags |= FLAG_HAS_DURATION;
args.pa_duration = duration;
break;
case 'm':
args.pa_flags |= FLAG_DO_ANNOTATE;
args.pa_plugin = PMCSTAT_PL_ANNOTATE;
@ -922,6 +934,12 @@ main(int argc, char **argv)
errx(EX_USAGE,
"ERROR: options -O and -R are mutually exclusive.");
/* disallow -T and -l together */
if ((args.pa_flags & FLAG_HAS_DURATION) &&
(args.pa_flags & FLAG_DO_TOP))
errx(EX_USAGE, "ERROR: options -T and -l are mutually "
"exclusive.");
/* -m option is allowed with -R only. */
if (args.pa_flags & FLAG_DO_ANNOTATE && args.pa_inputpath == NULL)
errx(EX_USAGE, "ERROR: option %s requires an input file",
@ -1279,6 +1297,20 @@ main(int argc, char **argv)
"ERROR: Cannot register kevent for timer");
}
/*
* Setup a duration timer if we have sampling mode PMCs and
* a duration time is set
*/
if ((args.pa_flags & FLAG_HAS_SAMPLING_PMCS) &&
(args.pa_flags & FLAG_HAS_DURATION)) {
EV_SET(&kev, 0, EVFILT_TIMER, EV_ADD, 0,
args.pa_duration * 1000, NULL);
if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
err(EX_OSERR, "ERROR: Cannot register kevent for "
"time duration");
}
/* attach PMCs to the target process, starting it if specified */
if (args.pa_flags & FLAG_HAS_COMMANDLINE)
pmcstat_create_process();
@ -1355,7 +1387,7 @@ main(int argc, char **argv)
/*
* loop till either the target process (if any) exits, or we
* are killed by a SIGINT.
* are killed by a SIGINT or we reached the time duration.
*/
runstate = PMCSTAT_RUNNING;
do_print = do_read = 0;
@ -1422,7 +1454,13 @@ main(int argc, char **argv)
break;
case EVFILT_TIMER: /* print out counting PMCs */
case EVFILT_TIMER:
/* time duration reached, exit */
if (args.pa_flags & FLAG_HAS_DURATION) {
runstate = PMCSTAT_FINISHED;
break;
}
/* print out counting PMCs */
if ((args.pa_flags & FLAG_DO_TOP) &&
pmc_flush_logfile() == 0)
do_read = 1;

View File

@ -54,6 +54,7 @@
#define FLAG_DO_TOP 0x00010000 /* -T */
#define FLAG_DO_ANALYSIS 0x00020000 /* -g or -G or -m or -T */
#define FLAGS_HAS_CPUMASK 0x00040000 /* -c */
#define FLAG_HAS_DURATION 0x00080000 /* -l secs */
#define DEFAULT_SAMPLE_COUNT 65536
#define DEFAULT_WAIT_INTERVAL 5.0
@ -149,6 +150,7 @@ struct pmcstat_args {
int pa_toptty; /* output to tty or file */
int pa_topcolor; /* terminal support color */
int pa_mergepmc; /* merge PMC with same name */
double pa_duration; /* time duration */
int pa_argc;
char **pa_argv;
STAILQ_HEAD(, pmcstat_ev) pa_events;