mirror of
https://github.com/opnsense/src.git
synced 2026-02-19 02:30:08 -05:00
pmcannotate: Add a '-m' mode option to control per-line annotations.
- "block" (the default mode) displays per-block percentages in front of each annotated line. - "global" displays a global percentage in front of each line. - "raw" displays the raw count of sample hits in front of each line. Reviewed by: Pau Amma <pauamma@gundo.com>, mav Sponsored by: University of Cambridge, Google, Inc. Differential Revision: https://reviews.freebsd.org/D35401 (cherry picked from commit de11299323e0a647ae2164f74ca966862e7c4dd8)
This commit is contained in:
parent
08f22bb41f
commit
067de34b8e
2 changed files with 60 additions and 9 deletions
|
|
@ -25,7 +25,7 @@
|
|||
.\" out of the use of this software, even if advised of the possibility of
|
||||
.\" such damage.
|
||||
.\"
|
||||
.Dd November 20, 2008
|
||||
.Dd January 14, 2025
|
||||
.Dt PMCANNOTATE 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -37,6 +37,7 @@
|
|||
.Op Fl h
|
||||
.Op Fl k Ar pathname
|
||||
.Op Fl l Ar level
|
||||
.Op Fl m Ar mode
|
||||
.Ar pmcout.out binaryobj
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
|
|
@ -84,6 +85,18 @@ This directory specifies where
|
|||
should look for the kernel and its modules.
|
||||
The default is
|
||||
.Pa /boot/kernel .
|
||||
.It Fl m Ar mode
|
||||
Format to use when annotating source or assembly lines.
|
||||
One of:
|
||||
.Bl -tag -width indent
|
||||
.It Cm block
|
||||
Display percentage of matching samples relative to samples
|
||||
falling in the current block.
|
||||
.It Cm global
|
||||
Display percentage of matching samples relative to all samples.
|
||||
.It Cm raw
|
||||
Display the raw count of matching samples.
|
||||
.El
|
||||
.El
|
||||
.Sh LIMITATIONS
|
||||
As long as
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <sys/queue.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -59,7 +60,7 @@
|
|||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
#define PERCSAMP(x) ((x) * 100 / totalsamples)
|
||||
#define PERCSAMP(x) ((float)(x) * 100 / totalsamples)
|
||||
|
||||
struct entry {
|
||||
TAILQ_ENTRY(entry) en_iter;
|
||||
|
|
@ -109,7 +110,9 @@ static TAILQ_HEAD(, aggent) fqueue = TAILQ_HEAD_INITIALIZER(fqueue);
|
|||
* Use a float value in order to automatically promote operations
|
||||
* to return a float value rather than use casts.
|
||||
*/
|
||||
static float totalsamples;
|
||||
static u_int totalsamples;
|
||||
|
||||
static enum { RAW, BLOCK_PERCENT, GLOBAL_PERCENT } print_mode;
|
||||
|
||||
/*
|
||||
* Identifies a string cointaining objdump's assembly printout.
|
||||
|
|
@ -501,6 +504,30 @@ general_insertent(struct entry *entry)
|
|||
TAILQ_INSERT_TAIL(&mainlst, entry, en_iter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string either holding a percentage or the raw count value.
|
||||
*/
|
||||
static const char *
|
||||
print_count(u_int nsamples, u_int totsamples)
|
||||
{
|
||||
static char buf[16];
|
||||
|
||||
switch (print_mode) {
|
||||
case RAW:
|
||||
snprintf(buf, sizeof(buf), "%u", nsamples);
|
||||
break;
|
||||
case BLOCK_PERCENT:
|
||||
snprintf(buf, sizeof(buf), "%.2f%%", (float)nsamples * 100 /
|
||||
totsamples);
|
||||
break;
|
||||
case GLOBAL_PERCENT:
|
||||
snprintf(buf, sizeof(buf), "%.2f%%", (float)nsamples * 100 /
|
||||
totalsamples);
|
||||
break;
|
||||
}
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Printout the body of an "objdump -d" assembly function.
|
||||
* It does simply stops when a new function is encountered,
|
||||
|
|
@ -529,8 +556,8 @@ general_printasm(FILE *fp, struct aggent *agg)
|
|||
if (obj == NULL)
|
||||
printf("\t| %s", buffer);
|
||||
else
|
||||
printf("%.2f%%\t| %s",
|
||||
(float)obj->en_nsamples * 100 / agg->ag_nsamples,
|
||||
printf("%7s | %s",
|
||||
print_count(obj->en_nsamples, agg->ag_nsamples),
|
||||
buffer);
|
||||
}
|
||||
}
|
||||
|
|
@ -623,8 +650,8 @@ printblock(FILE *fp, struct aggent *agg)
|
|||
printf("\t| %s", buffer);
|
||||
else {
|
||||
done = 1;
|
||||
printf("%.2f%%\t| %s",
|
||||
(float)tnsamples * 100 / agg->ag_nsamples, buffer);
|
||||
printf("%7s | %s",
|
||||
print_count(tnsamples, agg->ag_nsamples), buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -657,7 +684,7 @@ usage(const char *progname)
|
|||
{
|
||||
|
||||
fprintf(stderr,
|
||||
"usage: %s [-a] [-h] [-k kfile] [-l lb] pmcraw.out binary\n",
|
||||
"usage: %s [-a] [-h] [-k kfile] [-l lb] [-m mode] pmcraw.out binary\n",
|
||||
progname);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
|
@ -682,7 +709,8 @@ main(int argc, char *argv[])
|
|||
kfile = NULL;
|
||||
asmsrc = 0;
|
||||
limit = 0.5;
|
||||
while ((cget = getopt(argc, argv, "ahl:k:")) != -1)
|
||||
print_mode = BLOCK_PERCENT;
|
||||
while ((cget = getopt(argc, argv, "ahl:m:k:")) != -1)
|
||||
switch(cget) {
|
||||
case 'a':
|
||||
asmsrc = 1;
|
||||
|
|
@ -693,6 +721,16 @@ main(int argc, char *argv[])
|
|||
case 'l':
|
||||
limit = (float)atof(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
if (strcasecmp(optarg, "raw") == 0)
|
||||
print_mode = RAW;
|
||||
else if (strcasecmp(optarg, "global") == 0)
|
||||
print_mode = GLOBAL_PERCENT;
|
||||
else if (strcasecmp(optarg, "block") == 0)
|
||||
print_mode = BLOCK_PERCENT;
|
||||
else
|
||||
errx(1, "Invalid mode %s", optarg);
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
|
|
|
|||
Loading…
Reference in a new issue