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: