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 f Ar pluginopt
.Op Fl g .Op Fl g
.Op Fl k Ar kerneldir .Op Fl k Ar kerneldir
.Op Fl l Ar secs
.Op Fl m Ar pathname .Op Fl m Ar pathname
.Op Fl n Ar rate .Op Fl n Ar rate
.Op Fl o Ar outputfile .Op Fl o Ar outputfile
@ -274,6 +275,13 @@ This directory specifies where
should look for the kernel and its modules. should look for the kernel and its modules.
The default is The default is
.Pa /boot/kernel . .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 .It Fl m Ar pathname
Print the sampled PCs with the name, the start and ending addresses Print the sampled PCs with the name, the start and ending addresses
of the function within they live. 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 -f spec\t pass \"spec\" to as plugin option\n"
"\t -g\t\t produce gprof(1) compatible profiles\n" "\t -g\t\t produce gprof(1) compatible profiles\n"
"\t -k dir\t\t set the path to the kernel\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 -m file\t print sampled PCs to \"file\"\n"
"\t -n rate\t set sampling rate\n" "\t -n rate\t set sampling rate\n"
"\t -o file\t send print output to \"file\"\n" "\t -o file\t send print output to \"file\"\n"
@ -551,6 +552,7 @@ main(int argc, char **argv)
{ {
cpuset_t cpumask; cpuset_t cpumask;
double interval; double interval;
double duration;
int hcpu, option, npmc, ncpu; int hcpu, option, npmc, ncpu;
int c, check_driver_stats, current_sampling_count; int c, check_driver_stats, current_sampling_count;
int do_callchain, do_descendants, do_logproccsw, do_logprocexit; int do_callchain, do_descendants, do_logproccsw, do_logprocexit;
@ -600,6 +602,7 @@ main(int argc, char **argv)
args.pa_toptty = 0; args.pa_toptty = 0;
args.pa_topcolor = 0; args.pa_topcolor = 0;
args.pa_mergepmc = 0; args.pa_mergepmc = 0;
args.pa_duration = 0.0;
STAILQ_INIT(&args.pa_events); STAILQ_INIT(&args.pa_events);
SLIST_INIT(&args.pa_targets); SLIST_INIT(&args.pa_targets);
bzero(&ds_start, sizeof(ds_start)); bzero(&ds_start, sizeof(ds_start));
@ -618,7 +621,7 @@ main(int argc, char **argv)
CPU_SET(hcpu, &cpumask); CPU_SET(hcpu, &cpumask);
while ((option = getopt(argc, argv, 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) { switch (option) {
case 'a': /* Annotate + callgraph */ case 'a': /* Annotate + callgraph */
args.pa_flags |= FLAG_DO_ANNOTATE; args.pa_flags |= FLAG_DO_ANNOTATE;
@ -692,6 +695,15 @@ main(int argc, char **argv)
args.pa_flags |= FLAG_HAS_KERNELPATH; args.pa_flags |= FLAG_HAS_KERNELPATH;
break; 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': case 'm':
args.pa_flags |= FLAG_DO_ANNOTATE; args.pa_flags |= FLAG_DO_ANNOTATE;
args.pa_plugin = PMCSTAT_PL_ANNOTATE; args.pa_plugin = PMCSTAT_PL_ANNOTATE;
@ -922,6 +934,12 @@ main(int argc, char **argv)
errx(EX_USAGE, errx(EX_USAGE,
"ERROR: options -O and -R are mutually exclusive."); "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. */ /* -m option is allowed with -R only. */
if (args.pa_flags & FLAG_DO_ANNOTATE && args.pa_inputpath == NULL) if (args.pa_flags & FLAG_DO_ANNOTATE && args.pa_inputpath == NULL)
errx(EX_USAGE, "ERROR: option %s requires an input file", 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"); "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 */ /* attach PMCs to the target process, starting it if specified */
if (args.pa_flags & FLAG_HAS_COMMANDLINE) if (args.pa_flags & FLAG_HAS_COMMANDLINE)
pmcstat_create_process(); pmcstat_create_process();
@ -1355,7 +1387,7 @@ main(int argc, char **argv)
/* /*
* loop till either the target process (if any) exits, or we * 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; runstate = PMCSTAT_RUNNING;
do_print = do_read = 0; do_print = do_read = 0;
@ -1422,7 +1454,13 @@ main(int argc, char **argv)
break; 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) && if ((args.pa_flags & FLAG_DO_TOP) &&
pmc_flush_logfile() == 0) pmc_flush_logfile() == 0)
do_read = 1; do_read = 1;

View File

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