pmcstat: implement showing offsets into symbols in top mode

The -I option (and hotkey) is reused for this. Skipping symbol resolution is
moved to the new -A option (and hotkey).

While arguably this violates POLA I think it's a change for the better.
ALso note the -I option was added in head.

Differential Revision:	https://reviews.freebsd.org/D21658
This commit is contained in:
Mateusz Guzik 2020-08-05 19:05:49 +00:00
parent 5414a8285f
commit 94e9ef85c5
5 changed files with 60 additions and 24 deletions

View File

@ -107,8 +107,9 @@ struct pmcstat_args {
#define FLAGS_HAS_CPUMASK 0x00040000 /* -c */ #define FLAGS_HAS_CPUMASK 0x00040000 /* -c */
#define FLAG_HAS_DURATION 0x00080000 /* -l secs */ #define FLAG_HAS_DURATION 0x00080000 /* -l secs */
#define FLAG_DO_WIDE_GPROF_HC 0x00100000 /* -e */ #define FLAG_DO_WIDE_GPROF_HC 0x00100000 /* -e */
#define FLAG_SKIP_TOP_FN_RES 0x00200000 /* -I */ #define FLAG_SKIP_TOP_FN_RES 0x00200000 /* -A */
#define FLAG_FILTER_THREAD_ID 0x00400000 /* -L */ #define FLAG_FILTER_THREAD_ID 0x00400000 /* -L */
#define FLAG_SHOW_OFFSET 0x00800000 /* -I */
int pa_required; /* required features */ int pa_required; /* required features */
int pa_pplugin; /* pre-processing plugin */ int pa_pplugin; /* pre-processing plugin */

View File

@ -152,10 +152,12 @@ pmcstat_cgnode_hash_lookup_pc(struct pmcstat_process *pp, pmc_id_t pmcid,
* Try determine the function at this offset. If we can't * Try determine the function at this offset. If we can't
* find a function round leave the `pc' value alone. * find a function round leave the `pc' value alone.
*/ */
if ((sym = pmcstat_symbol_search(image, pc)) != NULL) if (!(args.pa_flags & (FLAG_SKIP_TOP_FN_RES | FLAG_SHOW_OFFSET))) {
pc = sym->ps_start; if ((sym = pmcstat_symbol_search(image, pc)) != NULL)
else pc = sym->ps_start;
pmcstat_stats.ps_samples_unknown_function++; else
pmcstat_stats.ps_samples_unknown_function++;
}
for (hash = i = 0; i < sizeof(uintfptr_t); i++) for (hash = i = 0; i < sizeof(uintfptr_t); i++)
hash += (pc >> i) & 0xFF; hash += (pc >> i) & 0xFF;
@ -485,22 +487,35 @@ pmcstat_cgnode_topprint(struct pmcstat_cgnode *cg,
v = PMCPL_CG_COUNTP(cg); v = PMCPL_CG_COUNTP(cg);
snprintf(vs, sizeof(vs), "%.1f", v); snprintf(vs, sizeof(vs), "%.1f", v);
v_attrs = PMCSTAT_ATTRPERCENT(v); v_attrs = PMCSTAT_ATTRPERCENT(v);
sym = NULL;
/* Format name. */ /* Format name. */
if (!(args.pa_flags & FLAG_SKIP_TOP_FN_RES)) sym = pmcstat_symbol_search(cg->pcg_image, cg->pcg_func);
sym = pmcstat_symbol_search(cg->pcg_image, cg->pcg_func); if (sym == NULL) {
if (sym != NULL) {
snprintf(ns, sizeof(ns), "%s",
pmcstat_string_unintern(sym->ps_name));
} else
snprintf(ns, sizeof(ns), "%p", snprintf(ns, sizeof(ns), "%p",
(void *)(cg->pcg_image->pi_vaddr + cg->pcg_func)); (void *)(cg->pcg_image->pi_vaddr + cg->pcg_func));
} else {
switch (args.pa_flags & (FLAG_SKIP_TOP_FN_RES | FLAG_SHOW_OFFSET)) {
case FLAG_SKIP_TOP_FN_RES | FLAG_SHOW_OFFSET:
case FLAG_SKIP_TOP_FN_RES:
snprintf(ns, sizeof(ns), "%p",
(void *)(cg->pcg_image->pi_vaddr + cg->pcg_func));
break;
case FLAG_SHOW_OFFSET:
snprintf(ns, sizeof(ns), "%s+%#0lx",
pmcstat_string_unintern(sym->ps_name),
cg->pcg_func - sym->ps_start);
break;
default:
snprintf(ns, sizeof(ns), "%s",
pmcstat_string_unintern(sym->ps_name));
break;
}
}
PMCSTAT_ATTRON(v_attrs); PMCSTAT_ATTRON(v_attrs);
PMCSTAT_PRINTW("%5.5s", vs); PMCSTAT_PRINTW("%5.5s", vs);
PMCSTAT_ATTROFF(v_attrs); PMCSTAT_ATTROFF(v_attrs);
PMCSTAT_PRINTW(" %-10.10s %-20.20s", PMCSTAT_PRINTW(" %-10.10s %-30.30s",
pmcstat_string_unintern(cg->pcg_image->pi_name), pmcstat_string_unintern(cg->pcg_image->pi_name),
ns); ns);
@ -624,7 +639,7 @@ pmcpl_cg_topdisplay(void)
qsort(sortbuffer, nentries, sizeof(struct pmcstat_cgnode *), qsort(sortbuffer, nentries, sizeof(struct pmcstat_cgnode *),
pmcstat_cgnode_compare); pmcstat_cgnode_compare);
PMCSTAT_PRINTW("%5.5s %-10.10s %-20.20s %s\n", PMCSTAT_PRINTW("%5.5s %-10.10s %-30.30s %s\n",
"%SAMP", "IMAGE", "FUNCTION", "CALLERS"); "%SAMP", "IMAGE", "FUNCTION", "CALLERS");
nentries = min(pmcstat_displayheight - 2, nentries); nentries = min(pmcstat_displayheight - 2, nentries);

View File

@ -25,7 +25,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd May 25, 2018 .Dd August 5, 2020
.Dt PMCSTAT 8 .Dt PMCSTAT 8
.Os .Os
.Sh NAME .Sh NAME
@ -33,6 +33,7 @@
.Nd "performance measurement with performance monitoring hardware" .Nd "performance measurement with performance monitoring hardware"
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl A
.Op Fl C .Op Fl C
.Op Fl D Ar pathname .Op Fl D Ar pathname
.Op Fl E .Op Fl E
@ -123,6 +124,8 @@ process' current and future children.
.Sh OPTIONS .Sh OPTIONS
The following options are available: The following options are available:
.Bl -tag -width indent .Bl -tag -width indent
.It Fl A
Skip symbol lookup and display address instead.
.It Fl C .It Fl C
Toggle between showing cumulative or incremental counts for Toggle between showing cumulative or incremental counts for
subsequent counting mode PMCs specified on the command line. subsequent counting mode PMCs specified on the command line.
@ -161,7 +164,7 @@ this information is sent to the output file specified by the
.Fl o .Fl o
option. option.
.It Fl I .It Fl I
Skip symbol lookup and display address instead. Show the offset of the instruction pointer into the symbol.
.It Fl L .It Fl L
List all event names. List all event names.
.It Fl M Ar mapfilename .It Fl M Ar mapfilename
@ -222,10 +225,10 @@ specified in
.Ar event-spec . .Ar event-spec .
.It Fl T .It Fl T
Use a top like mode for sampling PMCs. The following hotkeys Use a top like mode for sampling PMCs. The following hotkeys
can be used: 'c+a' switch to accumulative mode, 'c+d' switch can be used: 'A' toggle symbol resolution, 'c+a' switch to accumulative mode, 'c+d'
to delta mode, 'm' merge PMCs, 'n' change view, 'p' show next switch to delta mode, 'I' toggle showing offsets into symbols, 'm' merge PMCs, 'n'
PMC, ' ' pause, 'q' quit. calltree only: 'f' cost under threshold change view, 'p' show next PMC, ' ' pause, 'q' quit. calltree only: 'f' cost under
is seen as a dot. threshold is seen as a dot.
.It Fl U .It Fl U
Toggle capturing user-space call traces while in kernel mode. Toggle capturing user-space call traces while in kernel mode.
The default is for sampling PMCs to capture user-space callchain information The default is for sampling PMCs to capture user-space callchain information

View File

@ -511,8 +511,12 @@ main(int argc, char **argv)
CPU_COPY(&rootmask, &cpumask); CPU_COPY(&rootmask, &cpumask);
while ((option = getopt(argc, argv, while ((option = getopt(argc, argv,
"CD:EF:G:ILM:NO:P:R:S:TUWZa:c:def:gi:k:l:m:n:o:p:qr:s:t:u:vw:z:")) != -1) "ACD:EF:G:ILM:NO:P:R:S:TUWZa:c:def:gi:k:l:m:n:o:p:qr:s:t:u:vw:z:")) != -1)
switch (option) { switch (option) {
case 'A':
args.pa_flags |= FLAG_SKIP_TOP_FN_RES;
break;
case 'a': /* Annotate + callgraph */ case 'a': /* Annotate + callgraph */
args.pa_flags |= FLAG_DO_ANNOTATE; args.pa_flags |= FLAG_DO_ANNOTATE;
args.pa_plugin = PMCSTAT_PL_ANNOTATE_CG; args.pa_plugin = PMCSTAT_PL_ANNOTATE_CG;
@ -586,14 +590,15 @@ main(int argc, char **argv)
args.pa_plugin = PMCSTAT_PL_GPROF; args.pa_plugin = PMCSTAT_PL_GPROF;
break; break;
case 'I':
args.pa_flags |= FLAG_SKIP_TOP_FN_RES;
break;
case 'i': case 'i':
args.pa_flags |= FLAG_FILTER_THREAD_ID; args.pa_flags |= FLAG_FILTER_THREAD_ID;
args.pa_tid = strtol(optarg, &end, 0); args.pa_tid = strtol(optarg, &end, 0);
break; break;
case 'I':
args.pa_flags |= FLAG_SHOW_OFFSET;
break;
case 'k': /* pathname to the kernel */ case 'k': /* pathname to the kernel */
free(args.pa_kernel); free(args.pa_kernel);
args.pa_kernel = strdup(optarg); args.pa_kernel = strdup(optarg);

View File

@ -612,6 +612,12 @@ pmcstat_keypress_log(void)
c = wgetch(w); c = wgetch(w);
wprintw(w, "Key: %c => ", c); wprintw(w, "Key: %c => ", c);
switch (c) { switch (c) {
case 'A':
if (args.pa_flags & FLAG_SKIP_TOP_FN_RES)
args.pa_flags &= ~FLAG_SKIP_TOP_FN_RES;
else
args.pa_flags |= FLAG_SKIP_TOP_FN_RES;
break;
case 'c': case 'c':
wprintw(w, "enter mode 'd' or 'a' => "); wprintw(w, "enter mode 'd' or 'a' => ");
c = wgetch(w); c = wgetch(w);
@ -623,6 +629,12 @@ pmcstat_keypress_log(void)
wprintw(w, "switching to accumulation mode"); wprintw(w, "switching to accumulation mode");
} }
break; break;
case 'I':
if (args.pa_flags & FLAG_SHOW_OFFSET)
args.pa_flags &= ~FLAG_SHOW_OFFSET;
else
args.pa_flags |= FLAG_SHOW_OFFSET;
break;
case 'm': case 'm':
pmcstat_mergepmc = !pmcstat_mergepmc; pmcstat_mergepmc = !pmcstat_mergepmc;
/* /*