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:
parent
8dd2f31aad
commit
ab933b7bbb
|
@ -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
|
||||
|
|
|
@ -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(¶m, 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, ¶m);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue