git: 067de34b8e10 - stable/14 - pmcannotate: Add a '-m' mode option to control per-line annotations.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 27 Feb 2025 18:53:43 UTC
The branch stable/14 has been updated by jhb:
URL: https://cgit.FreeBSD.org/src/commit/?id=067de34b8e10448307fa402db6e83ff413f95e78
commit 067de34b8e10448307fa402db6e83ff413f95e78
Author: John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-01-14 15:39:53 +0000
Commit: John Baldwin <jhb@FreeBSD.org>
CommitDate: 2025-02-27 17:19:26 +0000
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)
---
usr.sbin/pmcannotate/pmcannotate.8 | 15 ++++++++++-
usr.sbin/pmcannotate/pmcannotate.c | 54 ++++++++++++++++++++++++++++++++------
2 files changed, 60 insertions(+), 9 deletions(-)
diff --git a/usr.sbin/pmcannotate/pmcannotate.8 b/usr.sbin/pmcannotate/pmcannotate.8
index 9a89c40db1e7..e2fae0a7a7e0 100644
--- a/usr.sbin/pmcannotate/pmcannotate.8
+++ b/usr.sbin/pmcannotate/pmcannotate.8
@@ -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
diff --git a/usr.sbin/pmcannotate/pmcannotate.c b/usr.sbin/pmcannotate/pmcannotate.c
index 32138aa6c3a7..c00e4b2a33bc 100644
--- a/usr.sbin/pmcannotate/pmcannotate.c
+++ b/usr.sbin/pmcannotate/pmcannotate.c
@@ -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: