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
5414a8285f
commit
94e9ef85c5
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user