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:
parent
e87c28bd39
commit
778c921d1a
@ -107,8 +107,9 @@ struct pmcstat_args {
|
||||
#define FLAGS_HAS_CPUMASK 0x00040000 /* -c */
|
||||
#define FLAG_HAS_DURATION 0x00080000 /* -l secs */
|
||||
#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_SHOW_OFFSET 0x00800000 /* -I */
|
||||
|
||||
int pa_required; /* required features */
|
||||
int pa_pplugin; /* pre-processing plugin */
|
||||
|
@ -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
|
||||
* find a function round leave the `pc' value alone.
|
||||
*/
|
||||
if ((sym = pmcstat_symbol_search(image, pc)) != NULL)
|
||||
pc = sym->ps_start;
|
||||
else
|
||||
pmcstat_stats.ps_samples_unknown_function++;
|
||||
if (!(args.pa_flags & (FLAG_SKIP_TOP_FN_RES | FLAG_SHOW_OFFSET))) {
|
||||
if ((sym = pmcstat_symbol_search(image, pc)) != NULL)
|
||||
pc = sym->ps_start;
|
||||
else
|
||||
pmcstat_stats.ps_samples_unknown_function++;
|
||||
}
|
||||
|
||||
for (hash = i = 0; i < sizeof(uintfptr_t); i++)
|
||||
hash += (pc >> i) & 0xFF;
|
||||
@ -485,22 +487,35 @@ pmcstat_cgnode_topprint(struct pmcstat_cgnode *cg,
|
||||
v = PMCPL_CG_COUNTP(cg);
|
||||
snprintf(vs, sizeof(vs), "%.1f", v);
|
||||
v_attrs = PMCSTAT_ATTRPERCENT(v);
|
||||
sym = NULL;
|
||||
|
||||
/* Format name. */
|
||||
if (!(args.pa_flags & FLAG_SKIP_TOP_FN_RES))
|
||||
sym = pmcstat_symbol_search(cg->pcg_image, cg->pcg_func);
|
||||
if (sym != NULL) {
|
||||
snprintf(ns, sizeof(ns), "%s",
|
||||
pmcstat_string_unintern(sym->ps_name));
|
||||
} else
|
||||
sym = pmcstat_symbol_search(cg->pcg_image, cg->pcg_func);
|
||||
if (sym == NULL) {
|
||||
snprintf(ns, sizeof(ns), "%p",
|
||||
(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_PRINTW("%5.5s", vs);
|
||||
PMCSTAT_ATTROFF(v_attrs);
|
||||
PMCSTAT_PRINTW(" %-10.10s %-20.20s",
|
||||
PMCSTAT_PRINTW(" %-10.10s %-30.30s",
|
||||
pmcstat_string_unintern(cg->pcg_image->pi_name),
|
||||
ns);
|
||||
|
||||
@ -624,7 +639,7 @@ pmcpl_cg_topdisplay(void)
|
||||
qsort(sortbuffer, nentries, sizeof(struct pmcstat_cgnode *),
|
||||
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");
|
||||
|
||||
nentries = min(pmcstat_displayheight - 2, nentries);
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 25, 2018
|
||||
.Dd August 5, 2020
|
||||
.Dt PMCSTAT 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -33,6 +33,7 @@
|
||||
.Nd "performance measurement with performance monitoring hardware"
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl A
|
||||
.Op Fl C
|
||||
.Op Fl D Ar pathname
|
||||
.Op Fl E
|
||||
@ -123,6 +124,8 @@ process' current and future children.
|
||||
.Sh OPTIONS
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl A
|
||||
Skip symbol lookup and display address instead.
|
||||
.It Fl C
|
||||
Toggle between showing cumulative or incremental counts for
|
||||
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
|
||||
option.
|
||||
.It Fl I
|
||||
Skip symbol lookup and display address instead.
|
||||
Show the offset of the instruction pointer into the symbol.
|
||||
.It Fl L
|
||||
List all event names.
|
||||
.It Fl M Ar mapfilename
|
||||
@ -222,10 +225,10 @@ specified in
|
||||
.Ar event-spec .
|
||||
.It Fl T
|
||||
Use a top like mode for sampling PMCs. The following hotkeys
|
||||
can be used: 'c+a' switch to accumulative mode, 'c+d' switch
|
||||
to delta mode, 'm' merge PMCs, 'n' change view, 'p' show next
|
||||
PMC, ' ' pause, 'q' quit. calltree only: 'f' cost under threshold
|
||||
is seen as a dot.
|
||||
can be used: 'A' toggle symbol resolution, 'c+a' switch to accumulative mode, 'c+d'
|
||||
switch to delta mode, 'I' toggle showing offsets into symbols, 'm' merge PMCs, 'n'
|
||||
change view, 'p' show next PMC, ' ' pause, 'q' quit. calltree only: 'f' cost under
|
||||
threshold is seen as a dot.
|
||||
.It Fl U
|
||||
Toggle capturing user-space call traces while in kernel mode.
|
||||
The default is for sampling PMCs to capture user-space callchain information
|
||||
|
@ -511,8 +511,12 @@ main(int argc, char **argv)
|
||||
CPU_COPY(&rootmask, &cpumask);
|
||||
|
||||
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) {
|
||||
case 'A':
|
||||
args.pa_flags |= FLAG_SKIP_TOP_FN_RES;
|
||||
break;
|
||||
|
||||
case 'a': /* Annotate + callgraph */
|
||||
args.pa_flags |= FLAG_DO_ANNOTATE;
|
||||
args.pa_plugin = PMCSTAT_PL_ANNOTATE_CG;
|
||||
@ -586,14 +590,15 @@ main(int argc, char **argv)
|
||||
args.pa_plugin = PMCSTAT_PL_GPROF;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
args.pa_flags |= FLAG_SKIP_TOP_FN_RES;
|
||||
break;
|
||||
case 'i':
|
||||
args.pa_flags |= FLAG_FILTER_THREAD_ID;
|
||||
args.pa_tid = strtol(optarg, &end, 0);
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
args.pa_flags |= FLAG_SHOW_OFFSET;
|
||||
break;
|
||||
|
||||
case 'k': /* pathname to the kernel */
|
||||
free(args.pa_kernel);
|
||||
args.pa_kernel = strdup(optarg);
|
||||
|
@ -612,6 +612,12 @@ pmcstat_keypress_log(void)
|
||||
c = wgetch(w);
|
||||
wprintw(w, "Key: %c => ", 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':
|
||||
wprintw(w, "enter mode 'd' or 'a' => ");
|
||||
c = wgetch(w);
|
||||
@ -623,6 +629,12 @@ pmcstat_keypress_log(void)
|
||||
wprintw(w, "switching to accumulation mode");
|
||||
}
|
||||
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':
|
||||
pmcstat_mergepmc = !pmcstat_mergepmc;
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user