Change the arguments of the tprof tool, to match the behavior of pmc(1) and

cpuctl(8). They become:

	tprof list
	tprof monitor -e name:option [-o outfile] command
This commit is contained in:
maxv 2018-07-13 09:04:31 +00:00
parent 8dd2f31aad
commit ab933b7bbb
2 changed files with 106 additions and 74 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: tprof.8,v 1.4 2018/07/13 07:56:29 maxv Exp $
.\" $NetBSD: tprof.8,v 1.5 2018/07/13 09:04:31 maxv Exp $
.\"
.\" Copyright (c)2011 YAMAMOTO Takashi,
.\" All rights reserved.
@ -32,16 +32,15 @@
.Nd record tprof profiling samples
.Sh SYNOPSIS
.Nm
.Op Fl l
.Op Fl e Ar name:option
.Op Fl c
.Op Fl o Ar file
.Ar command ...
.Ar op
.Op Ar arguments
.Sh DESCRIPTION
The
.Nm
is a sampling based profiler.
tool can be used to monitor hardware events (PMCs) during the execution of
certain commands.
.Pp
The
.Nm
utility makes the kernel driver start profiling,
executes the specified command,
@ -55,10 +54,21 @@ pseudo driver and a suitable backend should be loaded beforehand.
The
.Nm
utility accepts the following options.
.Bl -tag -width hogehoge
.It Fl l
The first argument,
.Ar op ,
specifies the action to take.
Valid actions are:
.Bl -tag -width offline
.It list
Display a list of performance counter events available on the system.
.It Fl e Ar name:option
.It monitor Xo
.Fl e
.Ar name:option
.Op Fl o Ar outfile
.Ar command
.Xc
Monitor the execution of command
.Ar command .
.Ar name
specifies the name of the event to count; it must be taken from the list of
available events.
@ -68,20 +78,16 @@ specifies the source of the event; it must be a combination of
(userland) and
.Ar k
(kernel).
.It Fl o Ar file
Write the collected samples to the file named
.Ar file .
The collected samples are written into the file
.Ar outfile
if specified.
The default is
.Dq Pa tprof.out .
.It Fl c
Write the collected samples to the standard output.
Note that the output is a binary stream.
.El
.Sh EXAMPLES
The following command profiles the system during 1 second and shows
the top-10 kernel functions which likely caused LLC misses.
.Bd -literal
tprof -e llc-misses:k -c sleep 1 2>/dev/null | tpfmt -skCLP | head -10
The following command profiles the system during 20 seconds and writes the
samples into the file myfile.out.
.Dl # tprof monitor -e llc-misses:k -o myfile.out sleep 20
.Ed
.Sh DIAGNOSTICS
The

View File

@ -1,4 +1,4 @@
/* $NetBSD: tprof.c,v 1.6 2018/07/13 07:56:29 maxv Exp $ */
/* $NetBSD: tprof.c,v 1.7 2018/07/13 09:04:31 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@ -57,7 +57,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: tprof.c,v 1.6 2018/07/13 07:56:29 maxv Exp $");
__RCSID("$NetBSD: tprof.c,v 1.7 2018/07/13 09:04:31 maxv Exp $");
#endif /* not lint */
#include <sys/ioctl.h>
@ -83,20 +83,31 @@ __RCSID("$NetBSD: tprof.c,v 1.6 2018/07/13 07:56:29 maxv Exp $");
int devfd;
int outfd;
static void tprof_list(int, char **);
static void tprof_monitor(int, char **);
static struct cmdtab {
const char *label;
bool takesargs;
bool argsoptional;
void (*func)(int, char **);
} const tprof_cmdtab[] = {
{ "list", false, false, tprof_list },
{ "monitor", true, false, tprof_monitor },
{ NULL, false, false, NULL },
};
__dead static void
usage(void)
{
fprintf(stderr, "%s [options] command ...\n", getprogname());
fprintf(stderr, "%s [op] [options] [command]\n", getprogname());
fprintf(stderr, "\n");
fprintf(stderr, "-e name:{u}{k}\t"
"the event to count.\n");
fprintf(stderr, "-l\t\t"
"list the events.\n");
fprintf(stderr, "-o filename\t"
"output to the file. [default: -o tprof.out]\n");
fprintf(stderr, "-c\t\t"
"output to stdout. NOTE: the output is a binary stream.\n");
fprintf(stderr, "\tlist\n");
fprintf(stderr, "\t\tList the available events.\n");
fprintf(stderr, "\tmonitor -e name:option [-o outfile] command\n");
fprintf(stderr, "\t\tMonitor the event 'name' with option 'option'\n"
"\t\tcounted during the execution of 'command'.\n");
exit(EXIT_FAILURE);
}
@ -132,48 +143,27 @@ process_samples(void *dummy)
return NULL;
}
int
main(int argc, char *argv[])
static void
tprof_list(int argc, char **argv)
{
tprof_event_list();
}
static void
tprof_monitor(int argc, char **argv)
{
struct tprof_param param;
struct tprof_info info;
struct tprof_stat ts;
const char *outfile = "tprof.out";
bool cflag = false;
struct tprof_param param;
struct tprof_stat ts;
pid_t pid;
pthread_t pt;
int error;
int ret;
int ch;
int ret, ch;
char *tokens[2];
memset(&param, 0, sizeof(param));
devfd = open(_PATH_TPROF, O_RDWR);
if (devfd == -1) {
err(EXIT_FAILURE, "%s", _PATH_TPROF);
}
ret = ioctl(devfd, TPROF_IOC_GETINFO, &info);
if (ret == -1) {
err(EXIT_FAILURE, "TPROF_IOC_GETINFO");
}
if (info.ti_version != TPROF_VERSION) {
errx(EXIT_FAILURE, "version mismatch: version=%d, expected=%d",
info.ti_version, TPROF_VERSION);
}
if (tprof_event_init(info.ti_ident) == -1) {
err(EXIT_FAILURE, "cpu not supported");
}
while ((ch = getopt(argc, argv, "clo:e:")) != -1) {
while ((ch = getopt(argc, argv, "o:e:")) != -1) {
switch (ch) {
case 'c':
cflag = true;
break;
case 'l':
tprof_event_list();
return 0;
case 'o':
outfile = optarg;
break;
@ -202,13 +192,9 @@ main(int argc, char *argv[])
usage();
}
if (cflag) {
outfd = STDOUT_FILENO;
} else {
outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (outfd == -1) {
err(EXIT_FAILURE, "%s", outfile);
}
outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (outfd == -1) {
err(EXIT_FAILURE, "%s", outfile);
}
ret = ioctl(devfd, TPROF_IOC_START, &param);
@ -228,9 +214,9 @@ main(int argc, char *argv[])
signal(SIGINT, SIG_IGN);
error = pthread_create(&pt, NULL, process_samples, NULL);
if (error != 0) {
errx(1, "pthread_create: %s", strerror(error));
ret = pthread_create(&pt, NULL, process_samples, NULL);
if (ret != 0) {
errx(1, "pthread_create: %s", strerror(ret));
}
for (;;) {
@ -270,3 +256,43 @@ main(int argc, char *argv[])
exit(EXIT_SUCCESS);
}
int
main(int argc, char *argv[])
{
struct tprof_info info;
const struct cmdtab *ct;
int ret;
setprogname(argv[0]);
argv += 1, argc -= 1;
devfd = open(_PATH_TPROF, O_RDWR);
if (devfd == -1) {
err(EXIT_FAILURE, "%s", _PATH_TPROF);
}
ret = ioctl(devfd, TPROF_IOC_GETINFO, &info);
if (ret == -1) {
err(EXIT_FAILURE, "TPROF_IOC_GETINFO");
}
if (info.ti_version != TPROF_VERSION) {
errx(EXIT_FAILURE, "version mismatch: version=%d, expected=%d",
info.ti_version, TPROF_VERSION);
}
if (tprof_event_init(info.ti_ident) == -1) {
err(EXIT_FAILURE, "cpu not supported");
}
for (ct = tprof_cmdtab; ct->label != NULL; ct++) {
if (strcmp(argv[0], ct->label) == 0) {
if (!ct->argsoptional &&
((ct->takesargs == 0) ^ (argv[1] == NULL)))
{
usage();
}
(*ct->func)(argc, argv);
break;
}
}
}