mirror of https://gitee.com/openkylin/linux.git
perf/core improvements and fixes:
- Show only failing syscalls with 'perf trace --failure' (Arnaldo Carvalho de Melo) e.g: See what 'openat' syscalls are failing: # perf trace --failure -e openat 762.323 ( 0.007 ms): VideoCapture/4566 openat(dfd: CWD, filename: /dev/video2) = -1 ENOENT No such file or directory <SNIP N /dev/videoN open attempts... sigh, where is that improvised camera lid?!? > 790.228 ( 0.008 ms): VideoCapture/4566 openat(dfd: CWD, filename: /dev/video63) = -1 ENOENT No such file or directory ^C# - Show information about the event (freq, nr_samples, total period/nr_events) in the annotate --tui and --stdio2 'perf annotate' output, similar to the first line in the 'perf report --tui', but just for the samples for a the annotated symbol (Arnaldo Carvalho de Melo) - Introduce 'perf version --build-options' to show what features were linked, aliased as well as a shorter 'perf -vv' (Jin Yao) - Add a "dso_size" sort order (Kim Phillips) - Remove redundant ')' in the tracepoint output in 'perf trace' (Changbin Du) - Synchronize x86's cpufeatures.h, no effect on toolss (Arnaldo Carvalho de Melo) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEELb9bqkb7Te0zijNb1lAW81NSqkAFAlrD3tIACgkQ1lAW81NS qkAPpQ//ZQ/8MTEGwoFTnuAM0D6Nu85i+0F8CBdryxDjPoE+g21eWKmcym/TUl4A PFB/i1ekVYt4hSpS4hIsfD4VQWcLeIOIKcTmPsJgqdhG56SbrnO+UOFWgNnLAuN5 4rwBXwRy1NFVy0E/O/kUxnsJRIzwvk8F9fWeynQ6TLp/cYAXdCC2w8hiHiKaJ+nF aTW+8BYktKUyVZHUDEtNhniYLhcmi70d2NrSd7/1Y8tRobB1yVMLs20pYs/T4vta aStA3GkDRShXcC9y426b+9AnG7Zjs4nQuMVIoIQbyReN2bIrC182G5OxepIG81bz rcnTiAhini52ZtlXIUs/s1x2vGXUCTbLtpwgim01huJjZ6qC6K7HeRqxGuhVHK/H DWddGTlnerwIzlBm1D1ubi5r0gi5phplkNBZPtUOmLLG7E1NnWpU7j2ikzlZkbwX v0IEDwt7Z/WFLhhUlGGloEq0zSYbj4o7YkTWFrU0C7wnW4nzRkXTxQfSL26HrMPY 5JaL3gppxVI3bbGeYVtzVoXQT30H8v85P2A0kx+1HnvwJ8AVQrnMqDr17BUT4/vo e3fmzOf5IjhEB52amwKSIGMcAglSIHg8Zdi72tJdPebvTZiDiuLWctmHBULeHUVh vPH6k1czzRj0FPDYME2vZCf7H+OFMxP2Cqqwkq7Ke4zTHvm1cIw= =tvR6 -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo-4.17-20180403' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: - Show only failing syscalls with 'perf trace --failure' (Arnaldo Carvalho de Melo) e.g: See what 'openat' syscalls are failing: # perf trace --failure -e openat 762.323 ( 0.007 ms): VideoCapture/4566 openat(dfd: CWD, filename: /dev/video2) = -1 ENOENT No such file or directory <SNIP N /dev/videoN open attempts... sigh, where is that improvised camera lid?!? > 790.228 ( 0.008 ms): VideoCapture/4566 openat(dfd: CWD, filename: /dev/video63) = -1 ENOENT No such file or directory ^C# - Show information about the event (freq, nr_samples, total period/nr_events) in the annotate --tui and --stdio2 'perf annotate' output, similar to the first line in the 'perf report --tui', but just for the samples for a the annotated symbol (Arnaldo Carvalho de Melo) - Introduce 'perf version --build-options' to show what features were linked, aliased as well as a shorter 'perf -vv' (Jin Yao) - Add a "dso_size" sort order (Kim Phillips) - Remove redundant ')' in the tracepoint output in 'perf trace' (Changbin Du) - Synchronize x86's cpufeatures.h, no effect on toolss (Arnaldo Carvalho de Melo) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
b89e7914f0
|
@ -316,6 +316,7 @@
|
|||
#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */
|
||||
#define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */
|
||||
#define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */
|
||||
#define X86_FEATURE_TME (16*32+13) /* Intel Total Memory Encryption */
|
||||
#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */
|
||||
#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */
|
||||
#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */
|
||||
|
@ -328,6 +329,7 @@
|
|||
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
|
||||
#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */
|
||||
#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
|
||||
#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
|
||||
#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */
|
||||
#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */
|
||||
#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _TOOLS_CONFIG_H
|
||||
#define _TOOLS_CONFIG_H
|
||||
|
||||
/* Subset of include/linux/kconfig.h */
|
||||
|
||||
#define __ARG_PLACEHOLDER_1 0,
|
||||
#define __take_second_arg(__ignored, val, ...) val
|
||||
|
||||
/*
|
||||
* Helper macros to use CONFIG_ options in C/CPP expressions. Note that
|
||||
* these only work with boolean and tristate options.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Getting something that works in C and CPP for an arg that may or may
|
||||
* not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1"
|
||||
* we match on the placeholder define, insert the "0," for arg1 and generate
|
||||
* the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one).
|
||||
* When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
|
||||
* the last step cherry picks the 2nd arg, we get a zero.
|
||||
*/
|
||||
#define __is_defined(x) ___is_defined(x)
|
||||
#define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val)
|
||||
#define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0)
|
||||
|
||||
/*
|
||||
* IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
|
||||
* otherwise. For boolean options, this is equivalent to
|
||||
* IS_ENABLED(CONFIG_FOO).
|
||||
*/
|
||||
#define IS_BUILTIN(option) __is_defined(option)
|
||||
|
||||
#endif /* _TOOLS_CONFIG_H */
|
|
@ -80,6 +80,7 @@ OPTIONS
|
|||
- comm: command (name) of the task which can be read via /proc/<pid>/comm
|
||||
- pid: command and tid of the task
|
||||
- dso: name of library or module executed at the time of sample
|
||||
- dso_size: size of library or module executed at the time of sample
|
||||
- symbol: name of function executed at the time of sample
|
||||
- symbol_size: size of function executed at the time of sample
|
||||
- parent: name of function matched to the parent regex filter. Unmatched
|
||||
|
|
|
@ -117,6 +117,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
|
|||
--sched::
|
||||
Accrue thread runtime and provide a summary at the end of the session.
|
||||
|
||||
--failure::
|
||||
Show only syscalls that failed, i.e. that returned < 0.
|
||||
|
||||
-i::
|
||||
--input::
|
||||
Process events from a given perf data file.
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
perf-version(1)
|
||||
===============
|
||||
|
||||
NAME
|
||||
----
|
||||
perf-version - display the version of perf binary
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'perf version' [--build-options]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
With no options given, the 'perf version' prints the perf version
|
||||
on the standard output.
|
||||
|
||||
If the option '--build-options' is given, then the status of
|
||||
compiled-in libraries are printed on the standard output.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
--build-options::
|
||||
Prints the status of compiled-in libraries on the
|
||||
standard output.
|
|
@ -346,12 +346,16 @@ else
|
|||
ifneq ($(feature-dwarf_getlocations), 1)
|
||||
msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157);
|
||||
else
|
||||
CFLAGS += -DHAVE_DWARF_GETLOCATIONS
|
||||
CFLAGS += -DHAVE_DWARF_GETLOCATIONS_SUPPORT
|
||||
endif # dwarf_getlocations
|
||||
endif # Dwarf support
|
||||
endif # libelf support
|
||||
endif # NO_LIBELF
|
||||
|
||||
ifeq ($(feature-glibc), 1)
|
||||
CFLAGS += -DHAVE_GLIBC_SUPPORT
|
||||
endif
|
||||
|
||||
ifdef NO_DWARF
|
||||
NO_LIBDW_DWARF_UNWIND := 1
|
||||
endif
|
||||
|
@ -635,6 +639,7 @@ else
|
|||
else
|
||||
LDFLAGS += $(PERL_EMBED_LDFLAGS)
|
||||
EXTLIBS += $(PERL_EMBED_LIBADD)
|
||||
CFLAGS += -DHAVE_LIBPERL_SUPPORT
|
||||
$(call detected,CONFIG_LIBPERL)
|
||||
endif
|
||||
endif
|
||||
|
@ -671,6 +676,7 @@ else
|
|||
LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
|
||||
EXTLIBS += $(PYTHON_EMBED_LIBADD)
|
||||
LANG_BINDINGS += $(obj-perf)python/perf.so
|
||||
CFLAGS += -DHAVE_LIBPYTHON_SUPPORT
|
||||
$(call detected,CONFIG_LIBPYTHON)
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -112,6 +112,7 @@ struct trace {
|
|||
bool multiple_threads;
|
||||
bool summary;
|
||||
bool summary_only;
|
||||
bool failure_only;
|
||||
bool show_comm;
|
||||
bool print_sample;
|
||||
bool show_tool_stats;
|
||||
|
@ -1565,7 +1566,7 @@ static int trace__printf_interrupted_entry(struct trace *trace)
|
|||
struct thread_trace *ttrace;
|
||||
size_t printed;
|
||||
|
||||
if (trace->current == NULL)
|
||||
if (trace->failure_only || trace->current == NULL)
|
||||
return 0;
|
||||
|
||||
ttrace = thread__priv(trace->current);
|
||||
|
@ -1638,7 +1639,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
|
|||
args, trace, thread);
|
||||
|
||||
if (sc->is_exit) {
|
||||
if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
|
||||
if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) {
|
||||
trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output);
|
||||
fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
|
||||
}
|
||||
|
@ -1742,7 +1743,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
|
|||
}
|
||||
}
|
||||
|
||||
if (trace->summary_only)
|
||||
if (trace->summary_only || (ret >= 0 && trace->failure_only))
|
||||
goto out;
|
||||
|
||||
trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output);
|
||||
|
@ -1961,7 +1962,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
|
|||
trace->output);
|
||||
}
|
||||
|
||||
fprintf(trace->output, ")\n");
|
||||
fprintf(trace->output, "\n");
|
||||
|
||||
if (callchain_ret > 0)
|
||||
trace__fprintf_callchain(trace, sample);
|
||||
|
@ -3087,6 +3088,8 @@ int cmd_trace(int argc, const char **argv)
|
|||
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
|
||||
OPT_BOOLEAN('T', "time", &trace.full_time,
|
||||
"Show full timestamp, not time relative to first start"),
|
||||
OPT_BOOLEAN(0, "failure", &trace.failure_only,
|
||||
"Show only syscalls that failed"),
|
||||
OPT_BOOLEAN('s', "summary", &trace.summary_only,
|
||||
"Show only syscall summary with statistics"),
|
||||
OPT_BOOLEAN('S', "with-summary", &trace.summary,
|
||||
|
|
|
@ -1,11 +1,91 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
#include "color.h"
|
||||
#include <linux/compiler.h>
|
||||
#include <tools/config.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
|
||||
int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused)
|
||||
int version_verbose;
|
||||
|
||||
struct version {
|
||||
bool build_options;
|
||||
};
|
||||
|
||||
static struct version version;
|
||||
|
||||
static struct option version_options[] = {
|
||||
OPT_BOOLEAN(0, "build-options", &version.build_options,
|
||||
"display the build options"),
|
||||
};
|
||||
|
||||
static const char * const version_usage[] = {
|
||||
"perf version [<options>]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void on_off_print(const char *status)
|
||||
{
|
||||
printf("[ ");
|
||||
|
||||
if (!strcmp(status, "OFF"))
|
||||
color_fprintf(stdout, PERF_COLOR_RED, "%-3s", status);
|
||||
else
|
||||
color_fprintf(stdout, PERF_COLOR_GREEN, "%-3s", status);
|
||||
|
||||
printf(" ]");
|
||||
}
|
||||
|
||||
static void status_print(const char *name, const char *macro,
|
||||
const char *status)
|
||||
{
|
||||
printf("%22s: ", name);
|
||||
on_off_print(status);
|
||||
printf(" # %s\n", macro);
|
||||
}
|
||||
|
||||
#define STATUS(__d, __m) \
|
||||
do { \
|
||||
if (IS_BUILTIN(__d)) \
|
||||
status_print(#__m, #__d, "on"); \
|
||||
else \
|
||||
status_print(#__m, #__d, "OFF"); \
|
||||
} while (0)
|
||||
|
||||
static void library_status(void)
|
||||
{
|
||||
STATUS(HAVE_DWARF_SUPPORT, dwarf);
|
||||
STATUS(HAVE_DWARF_GETLOCATIONS_SUPPORT, dwarf_getlocations);
|
||||
STATUS(HAVE_GLIBC_SUPPORT, glibc);
|
||||
STATUS(HAVE_GTK2_SUPPORT, gtk2);
|
||||
STATUS(HAVE_LIBAUDIT_SUPPORT, libaudit);
|
||||
STATUS(HAVE_LIBBFD_SUPPORT, libbfd);
|
||||
STATUS(HAVE_LIBELF_SUPPORT, libelf);
|
||||
STATUS(HAVE_LIBNUMA_SUPPORT, libnuma);
|
||||
STATUS(HAVE_LIBNUMA_SUPPORT, numa_num_possible_cpus);
|
||||
STATUS(HAVE_LIBPERL_SUPPORT, libperl);
|
||||
STATUS(HAVE_LIBPYTHON_SUPPORT, libpython);
|
||||
STATUS(HAVE_SLANG_SUPPORT, libslang);
|
||||
STATUS(HAVE_LIBCRYPTO_SUPPORT, libcrypto);
|
||||
STATUS(HAVE_LIBUNWIND_SUPPORT, libunwind);
|
||||
STATUS(HAVE_DWARF_SUPPORT, libdw-dwarf-unwind);
|
||||
STATUS(HAVE_ZLIB_SUPPORT, zlib);
|
||||
STATUS(HAVE_LZMA_SUPPORT, lzma);
|
||||
STATUS(HAVE_AUXTRACE_SUPPORT, get_cpuid);
|
||||
STATUS(HAVE_LIBBPF_SUPPORT, bpf);
|
||||
}
|
||||
|
||||
int cmd_version(int argc, const char **argv)
|
||||
{
|
||||
argc = parse_options(argc, argv, version_options, version_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
||||
printf("perf version %s\n", perf_version_string);
|
||||
|
||||
if (version.build_options || version_verbose == 1)
|
||||
library_status();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -190,6 +190,12 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!strcmp(cmd, "-vv")) {
|
||||
(*argv)[0] = "version";
|
||||
version_verbose = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check remaining flags.
|
||||
*/
|
||||
|
|
|
@ -84,6 +84,7 @@ struct record_opts {
|
|||
struct option;
|
||||
extern const char * const *record_usage;
|
||||
extern struct option *record_options;
|
||||
extern int version_verbose;
|
||||
|
||||
int record__parse_freq(const struct option *opt, const char *str, int unset);
|
||||
#endif
|
||||
|
|
|
@ -45,11 +45,16 @@ void ui_browser__set_percent_color(struct ui_browser *browser,
|
|||
ui_browser__set_color(browser, color);
|
||||
}
|
||||
|
||||
void ui_browser__gotorc(struct ui_browser *browser, int y, int x)
|
||||
void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x)
|
||||
{
|
||||
SLsmg_gotorc(browser->y + y, browser->x + x);
|
||||
}
|
||||
|
||||
void ui_browser__gotorc(struct ui_browser *browser, int y, int x)
|
||||
{
|
||||
SLsmg_gotorc(browser->y + y + browser->extra_title_lines, browser->x + x);
|
||||
}
|
||||
|
||||
void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg,
|
||||
unsigned int width)
|
||||
{
|
||||
|
@ -191,6 +196,7 @@ void ui_browser__refresh_dimensions(struct ui_browser *browser)
|
|||
{
|
||||
browser->width = SLtt_Screen_Cols - 1;
|
||||
browser->height = browser->rows = SLtt_Screen_Rows - 2;
|
||||
browser->rows -= browser->extra_title_lines;
|
||||
browser->y = 1;
|
||||
browser->x = 0;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ struct ui_browser {
|
|||
u64 index, top_idx;
|
||||
void *top, *entries;
|
||||
u16 y, x, width, height, rows, columns, horiz_scroll;
|
||||
u8 extra_title_lines;
|
||||
int current_color;
|
||||
void *priv;
|
||||
const char *title;
|
||||
|
@ -38,6 +39,7 @@ bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row);
|
|||
void ui_browser__refresh_dimensions(struct ui_browser *browser);
|
||||
void ui_browser__reset_index(struct ui_browser *browser);
|
||||
|
||||
void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x);
|
||||
void ui_browser__gotorc(struct ui_browser *browser, int y, int x);
|
||||
void ui_browser__write_nstring(struct ui_browser *browser, const char *msg,
|
||||
unsigned int width);
|
||||
|
|
|
@ -592,21 +592,40 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
|
|||
return __annotate_browser__search_reverse(browser);
|
||||
}
|
||||
|
||||
static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help)
|
||||
{
|
||||
struct map_symbol *ms = browser->priv;
|
||||
struct symbol *sym = ms->sym;
|
||||
char symbol_dso[SYM_TITLE_MAX_SIZE];
|
||||
|
||||
if (ui_browser__show(browser, title, help) < 0)
|
||||
return -1;
|
||||
|
||||
sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso));
|
||||
|
||||
ui_browser__gotorc_title(browser, 0, 0);
|
||||
ui_browser__set_color(browser, HE_COLORSET_ROOT);
|
||||
ui_browser__write_nstring(browser, symbol_dso, browser->width + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int annotate_browser__run(struct annotate_browser *browser,
|
||||
struct perf_evsel *evsel,
|
||||
struct hist_browser_timer *hbt)
|
||||
{
|
||||
struct rb_node *nd = NULL;
|
||||
struct hists *hists = evsel__hists(evsel);
|
||||
struct map_symbol *ms = browser->b.priv;
|
||||
struct symbol *sym = ms->sym;
|
||||
struct annotation *notes = symbol__annotation(ms->sym);
|
||||
const char *help = "Press 'h' for help on key bindings";
|
||||
int delay_secs = hbt ? hbt->refresh : 0;
|
||||
char title[256];
|
||||
int key;
|
||||
char title[SYM_TITLE_MAX_SIZE];
|
||||
|
||||
sym_title(sym, ms->map, title, sizeof(title));
|
||||
if (ui_browser__show(&browser->b, title, help) < 0)
|
||||
annotation__scnprintf_samples_period(notes, title, sizeof(title), evsel);
|
||||
|
||||
if (annotate_browser__show(&browser->b, title, help) < 0)
|
||||
return -1;
|
||||
|
||||
annotate_browser__calc_percent(browser, evsel);
|
||||
|
@ -637,8 +656,11 @@ static int annotate_browser__run(struct annotate_browser *browser,
|
|||
if (hbt)
|
||||
hbt->timer(hbt->arg);
|
||||
|
||||
if (delay_secs != 0)
|
||||
if (delay_secs != 0) {
|
||||
symbol__annotate_decay_histogram(sym, evsel->idx);
|
||||
hists__scnprintf_title(hists, title, sizeof(title));
|
||||
annotate_browser__show(&browser->b, title, help);
|
||||
}
|
||||
continue;
|
||||
case K_TAB:
|
||||
if (nd != NULL) {
|
||||
|
@ -812,6 +834,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
|
|||
.seek = ui_browser__list_head_seek,
|
||||
.write = annotate_browser__write,
|
||||
.filter = disasm_line__filter,
|
||||
.extra_title_lines = 1, /* for hists__scnprintf_title() */
|
||||
.priv = &ms,
|
||||
.use_navkeypressed = true,
|
||||
},
|
||||
|
|
|
@ -32,8 +32,7 @@
|
|||
|
||||
extern void hist_browser__init_hpp(void);
|
||||
|
||||
static int perf_evsel_browser_title(struct hist_browser *browser,
|
||||
char *bf, size_t size);
|
||||
static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size);
|
||||
static void hist_browser__update_nr_entries(struct hist_browser *hb);
|
||||
|
||||
static struct rb_node *hists__filter_entries(struct rb_node *nd,
|
||||
|
@ -62,6 +61,15 @@ static int hist_browser__get_folding(struct hist_browser *browser)
|
|||
return unfolded_rows;
|
||||
}
|
||||
|
||||
static void hist_browser__set_title_space(struct hist_browser *hb)
|
||||
{
|
||||
struct ui_browser *browser = &hb->b;
|
||||
struct hists *hists = hb->hists;
|
||||
struct perf_hpp_list *hpp_list = hists->hpp_list;
|
||||
|
||||
browser->extra_title_lines = hb->show_headers ? hpp_list->nr_header_lines : 0;
|
||||
}
|
||||
|
||||
static u32 hist_browser__nr_entries(struct hist_browser *hb)
|
||||
{
|
||||
u32 nr_entries;
|
||||
|
@ -82,10 +90,16 @@ static void hist_browser__update_rows(struct hist_browser *hb)
|
|||
struct ui_browser *browser = &hb->b;
|
||||
struct hists *hists = hb->hists;
|
||||
struct perf_hpp_list *hpp_list = hists->hpp_list;
|
||||
u16 header_offset, index_row;
|
||||
u16 index_row;
|
||||
|
||||
header_offset = hb->show_headers ? hpp_list->nr_header_lines : 0;
|
||||
browser->rows = browser->height - header_offset;
|
||||
if (!hb->show_headers) {
|
||||
browser->rows += browser->extra_title_lines;
|
||||
browser->extra_title_lines = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
browser->extra_title_lines = hpp_list->nr_header_lines;
|
||||
browser->rows -= browser->extra_title_lines;
|
||||
/*
|
||||
* Verify if we were at the last line and that line isn't
|
||||
* visibe because we now show the header line(s).
|
||||
|
@ -108,17 +122,6 @@ static void hist_browser__refresh_dimensions(struct ui_browser *browser)
|
|||
* changeset.
|
||||
*/
|
||||
ui_browser__refresh_dimensions(browser);
|
||||
hist_browser__update_rows(hb);
|
||||
}
|
||||
|
||||
static void hist_browser__gotorc(struct hist_browser *browser, int row, int column)
|
||||
{
|
||||
struct hists *hists = browser->hists;
|
||||
struct perf_hpp_list *hpp_list = hists->hpp_list;
|
||||
u16 header_offset;
|
||||
|
||||
header_offset = browser->show_headers ? hpp_list->nr_header_lines : 0;
|
||||
ui_browser__gotorc(&browser->b, row + header_offset, column);
|
||||
}
|
||||
|
||||
static void hist_browser__reset(struct hist_browser *browser)
|
||||
|
@ -733,7 +736,7 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
|
|||
}
|
||||
|
||||
ui_browser__set_color(&browser->b, color);
|
||||
hist_browser__gotorc(browser, row, 0);
|
||||
ui_browser__gotorc(&browser->b, row, 0);
|
||||
ui_browser__write_nstring(&browser->b, " ", offset);
|
||||
ui_browser__printf(&browser->b, "%c", folded_sign);
|
||||
ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' ');
|
||||
|
@ -1249,7 +1252,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
|
|||
};
|
||||
int column = 0;
|
||||
|
||||
hist_browser__gotorc(browser, row, 0);
|
||||
ui_browser__gotorc(&browser->b, row, 0);
|
||||
|
||||
hists__for_each_format(browser->hists, fmt) {
|
||||
char s[2048];
|
||||
|
@ -1358,7 +1361,7 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
|
|||
goto show_callchain;
|
||||
}
|
||||
|
||||
hist_browser__gotorc(browser, row, 0);
|
||||
ui_browser__gotorc(&browser->b, row, 0);
|
||||
|
||||
if (current_entry && browser->b.navkeypressed)
|
||||
ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED);
|
||||
|
@ -1507,7 +1510,7 @@ static int hist_browser__show_no_entry(struct hist_browser *browser,
|
|||
browser->selection = NULL;
|
||||
}
|
||||
|
||||
hist_browser__gotorc(browser, row, 0);
|
||||
ui_browser__gotorc(&browser->b, row, 0);
|
||||
|
||||
if (current_entry && browser->b.navkeypressed)
|
||||
ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED);
|
||||
|
@ -1713,7 +1716,7 @@ static void hists_browser__headers(struct hist_browser *browser)
|
|||
hists_browser__scnprintf_headers(browser, headers,
|
||||
sizeof(headers), line);
|
||||
|
||||
ui_browser__gotorc(&browser->b, line, 0);
|
||||
ui_browser__gotorc_title(&browser->b, line, 0);
|
||||
ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
|
||||
ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
|
||||
}
|
||||
|
@ -2143,6 +2146,7 @@ void hist_browser__init(struct hist_browser *browser,
|
|||
browser->b.seek = ui_browser__hists_seek;
|
||||
browser->b.use_navkeypressed = true;
|
||||
browser->show_headers = symbol_conf.show_hist_headers;
|
||||
hist_browser__set_title_space(browser);
|
||||
|
||||
if (symbol_conf.report_hierarchy) {
|
||||
struct perf_hpp_list_node *fmt_node;
|
||||
|
@ -2183,7 +2187,7 @@ perf_evsel_browser__new(struct perf_evsel *evsel,
|
|||
if (browser) {
|
||||
browser->hbt = hbt;
|
||||
browser->env = env;
|
||||
browser->title = perf_evsel_browser_title;
|
||||
browser->title = hists_browser__scnprintf_title;
|
||||
}
|
||||
return browser;
|
||||
}
|
||||
|
@ -2209,84 +2213,11 @@ static inline bool is_report_browser(void *timer)
|
|||
return timer == NULL;
|
||||
}
|
||||
|
||||
static int perf_evsel_browser_title(struct hist_browser *browser,
|
||||
char *bf, size_t size)
|
||||
static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size)
|
||||
{
|
||||
struct hist_browser_timer *hbt = browser->hbt;
|
||||
struct hists *hists = browser->hists;
|
||||
char unit;
|
||||
int printed;
|
||||
const struct dso *dso = hists->dso_filter;
|
||||
const struct thread *thread = hists->thread_filter;
|
||||
int socket_id = hists->socket_filter;
|
||||
unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
|
||||
u64 nr_events = hists->stats.total_period;
|
||||
struct perf_evsel *evsel = hists_to_evsel(hists);
|
||||
const char *ev_name = perf_evsel__name(evsel);
|
||||
char buf[512], sample_freq_str[64] = "";
|
||||
size_t buflen = sizeof(buf);
|
||||
char ref[30] = " show reference callgraph, ";
|
||||
bool enable_ref = false;
|
||||
int printed = __hists__scnprintf_title(browser->hists, bf, size, !is_report_browser(hbt));
|
||||
|
||||
if (symbol_conf.filter_relative) {
|
||||
nr_samples = hists->stats.nr_non_filtered_samples;
|
||||
nr_events = hists->stats.total_non_filtered_period;
|
||||
}
|
||||
|
||||
if (perf_evsel__is_group_event(evsel)) {
|
||||
struct perf_evsel *pos;
|
||||
|
||||
perf_evsel__group_desc(evsel, buf, buflen);
|
||||
ev_name = buf;
|
||||
|
||||
for_each_group_member(pos, evsel) {
|
||||
struct hists *pos_hists = evsel__hists(pos);
|
||||
|
||||
if (symbol_conf.filter_relative) {
|
||||
nr_samples += pos_hists->stats.nr_non_filtered_samples;
|
||||
nr_events += pos_hists->stats.total_non_filtered_period;
|
||||
} else {
|
||||
nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
|
||||
nr_events += pos_hists->stats.total_period;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol_conf.show_ref_callgraph &&
|
||||
strstr(ev_name, "call-graph=no"))
|
||||
enable_ref = true;
|
||||
|
||||
if (!is_report_browser(hbt))
|
||||
scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
|
||||
|
||||
nr_samples = convert_unit(nr_samples, &unit);
|
||||
printed = scnprintf(bf, size,
|
||||
"Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
|
||||
nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
|
||||
ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
|
||||
|
||||
|
||||
if (hists->uid_filter_str)
|
||||
printed += snprintf(bf + printed, size - printed,
|
||||
", UID: %s", hists->uid_filter_str);
|
||||
if (thread) {
|
||||
if (hists__has(hists, thread)) {
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
", Thread: %s(%d)",
|
||||
(thread->comm_set ? thread__comm_str(thread) : ""),
|
||||
thread->tid);
|
||||
} else {
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
", Thread: %s",
|
||||
(thread->comm_set ? thread__comm_str(thread) : ""));
|
||||
}
|
||||
}
|
||||
if (dso)
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
", DSO: %s", dso->short_name);
|
||||
if (socket_id > -1)
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
", Processor Socket: %d", socket_id);
|
||||
if (!is_report_browser(hbt)) {
|
||||
struct perf_top *top = hbt->arg;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "config.h"
|
||||
#include "cache.h"
|
||||
#include "symbol.h"
|
||||
#include "units.h"
|
||||
#include "debug.h"
|
||||
#include "annotate.h"
|
||||
#include "evsel.h"
|
||||
|
@ -2324,7 +2325,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
|
|||
struct dso *dso = map->dso;
|
||||
struct rb_root source_line = RB_ROOT;
|
||||
struct annotation_options opts = annotation__default_options;
|
||||
const char *ev_name = perf_evsel__name(evsel);
|
||||
struct annotation *notes = symbol__annotation(sym);
|
||||
char buf[1024];
|
||||
|
||||
if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0)
|
||||
|
@ -2336,12 +2337,8 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
|
|||
print_summary(&source_line, dso->long_name);
|
||||
}
|
||||
|
||||
if (perf_evsel__is_group_event(evsel)) {
|
||||
perf_evsel__group_desc(evsel, buf, sizeof(buf));
|
||||
ev_name = buf;
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s() %s\nEvent: %s\n\n", sym->name, dso->long_name, ev_name);
|
||||
annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel);
|
||||
fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name);
|
||||
symbol__annotate_fprintf2(sym, stdout);
|
||||
|
||||
annotated_source__purge(symbol__annotation(sym)->src);
|
||||
|
@ -2597,6 +2594,43 @@ int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *ev
|
|||
return -1;
|
||||
}
|
||||
|
||||
int __annotation__scnprintf_samples_period(struct annotation *notes,
|
||||
char *bf, size_t size,
|
||||
struct perf_evsel *evsel,
|
||||
bool show_freq)
|
||||
{
|
||||
const char *ev_name = perf_evsel__name(evsel);
|
||||
char ref[30] = " show reference callgraph, ";
|
||||
char sample_freq_str[64] = "";
|
||||
unsigned long nr_samples = 0;
|
||||
int nr_members = 1;
|
||||
bool enable_ref = false;
|
||||
u64 nr_events = 0;
|
||||
char unit;
|
||||
int i;
|
||||
|
||||
if (perf_evsel__is_group_event(evsel))
|
||||
nr_members = evsel->nr_members;
|
||||
|
||||
for (i = 0; i < nr_members; i++) {
|
||||
struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i);
|
||||
|
||||
nr_samples += ah->nr_samples;
|
||||
nr_events += ah->period;
|
||||
}
|
||||
|
||||
if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no"))
|
||||
enable_ref = true;
|
||||
|
||||
if (show_freq)
|
||||
scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
|
||||
|
||||
nr_samples = convert_unit(nr_samples, &unit);
|
||||
return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
|
||||
nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
|
||||
ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
|
||||
}
|
||||
|
||||
#define ANNOTATION__CFG(n) \
|
||||
{ .name = #n, .value = &annotation__default_options.n, }
|
||||
|
||||
|
|
|
@ -151,6 +151,18 @@ double annotation_line__max_percent(struct annotation_line *al, struct annotatio
|
|||
void annotation_line__write(struct annotation_line *al, struct annotation *notes,
|
||||
struct annotation_write_ops *ops);
|
||||
|
||||
int __annotation__scnprintf_samples_period(struct annotation *notes,
|
||||
char *bf, size_t size,
|
||||
struct perf_evsel *evsel,
|
||||
bool show_freq);
|
||||
|
||||
static inline int annotation__scnprintf_samples_period(struct annotation *notes,
|
||||
char *bf, size_t size,
|
||||
struct perf_evsel *evsel)
|
||||
{
|
||||
return __annotation__scnprintf_samples_period(notes, bf, size, evsel, true);
|
||||
}
|
||||
|
||||
int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
|
||||
size_t disasm__fprintf(struct list_head *head, FILE *fp);
|
||||
void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
|
||||
|
|
|
@ -979,7 +979,7 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
|
|||
return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
|
||||
}
|
||||
|
||||
#ifdef HAVE_DWARF_GETLOCATIONS
|
||||
#ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
|
||||
/**
|
||||
* die_get_var_innermost_scope - Get innermost scope range of given variable DIE
|
||||
* @sp_die: a subprogram DIE
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "session.h"
|
||||
#include "namespaces.h"
|
||||
#include "sort.h"
|
||||
#include "units.h"
|
||||
#include "evlist.h"
|
||||
#include "evsel.h"
|
||||
#include "annotate.h"
|
||||
|
@ -14,6 +15,7 @@
|
|||
#include "ui/progress.h"
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
static bool hists__filter_entry_by_dso(struct hists *hists,
|
||||
|
@ -2454,6 +2456,85 @@ u64 hists__total_period(struct hists *hists)
|
|||
hists->stats.total_period;
|
||||
}
|
||||
|
||||
int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq)
|
||||
{
|
||||
char unit;
|
||||
int printed;
|
||||
const struct dso *dso = hists->dso_filter;
|
||||
const struct thread *thread = hists->thread_filter;
|
||||
int socket_id = hists->socket_filter;
|
||||
unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
|
||||
u64 nr_events = hists->stats.total_period;
|
||||
struct perf_evsel *evsel = hists_to_evsel(hists);
|
||||
const char *ev_name = perf_evsel__name(evsel);
|
||||
char buf[512], sample_freq_str[64] = "";
|
||||
size_t buflen = sizeof(buf);
|
||||
char ref[30] = " show reference callgraph, ";
|
||||
bool enable_ref = false;
|
||||
|
||||
if (symbol_conf.filter_relative) {
|
||||
nr_samples = hists->stats.nr_non_filtered_samples;
|
||||
nr_events = hists->stats.total_non_filtered_period;
|
||||
}
|
||||
|
||||
if (perf_evsel__is_group_event(evsel)) {
|
||||
struct perf_evsel *pos;
|
||||
|
||||
perf_evsel__group_desc(evsel, buf, buflen);
|
||||
ev_name = buf;
|
||||
|
||||
for_each_group_member(pos, evsel) {
|
||||
struct hists *pos_hists = evsel__hists(pos);
|
||||
|
||||
if (symbol_conf.filter_relative) {
|
||||
nr_samples += pos_hists->stats.nr_non_filtered_samples;
|
||||
nr_events += pos_hists->stats.total_non_filtered_period;
|
||||
} else {
|
||||
nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
|
||||
nr_events += pos_hists->stats.total_period;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol_conf.show_ref_callgraph &&
|
||||
strstr(ev_name, "call-graph=no"))
|
||||
enable_ref = true;
|
||||
|
||||
if (show_freq)
|
||||
scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
|
||||
|
||||
nr_samples = convert_unit(nr_samples, &unit);
|
||||
printed = scnprintf(bf, size,
|
||||
"Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
|
||||
nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
|
||||
ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
|
||||
|
||||
|
||||
if (hists->uid_filter_str)
|
||||
printed += snprintf(bf + printed, size - printed,
|
||||
", UID: %s", hists->uid_filter_str);
|
||||
if (thread) {
|
||||
if (hists__has(hists, thread)) {
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
", Thread: %s(%d)",
|
||||
(thread->comm_set ? thread__comm_str(thread) : ""),
|
||||
thread->tid);
|
||||
} else {
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
", Thread: %s",
|
||||
(thread->comm_set ? thread__comm_str(thread) : ""));
|
||||
}
|
||||
}
|
||||
if (dso)
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
", DSO: %s", dso->short_name);
|
||||
if (socket_id > -1)
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
", Processor Socket: %d", socket_id);
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
||||
int parse_filter_percentage(const struct option *opt __maybe_unused,
|
||||
const char *arg, int unset __maybe_unused)
|
||||
{
|
||||
|
|
|
@ -61,6 +61,7 @@ enum hist_column {
|
|||
HISTC_SRCLINE_TO,
|
||||
HISTC_TRACE,
|
||||
HISTC_SYM_SIZE,
|
||||
HISTC_DSO_SIZE,
|
||||
HISTC_NR_COLS, /* Last entry */
|
||||
};
|
||||
|
||||
|
@ -503,5 +504,11 @@ int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...);
|
|||
int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp,
|
||||
struct perf_hpp_list *hpp_list);
|
||||
int hists__fprintf_headers(struct hists *hists, FILE *fp);
|
||||
int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq);
|
||||
|
||||
static inline int hists__scnprintf_title(struct hists *hists, char *bf, size_t size)
|
||||
{
|
||||
return __hists__scnprintf_title(hists, bf, size, true);
|
||||
}
|
||||
|
||||
#endif /* __PERF_HIST_H */
|
||||
|
|
|
@ -103,6 +103,10 @@ static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip)
|
|||
return ip;
|
||||
}
|
||||
|
||||
static inline size_t map__size(const struct map *map)
|
||||
{
|
||||
return map->end - map->start;
|
||||
}
|
||||
|
||||
/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */
|
||||
u64 map__rip_2objdump(struct map *map, u64 rip);
|
||||
|
|
|
@ -1545,6 +1545,46 @@ struct sort_entry sort_sym_size = {
|
|||
.se_width_idx = HISTC_SYM_SIZE,
|
||||
};
|
||||
|
||||
/* --sort dso_size */
|
||||
|
||||
static int64_t _sort__dso_size_cmp(struct map *map_l, struct map *map_r)
|
||||
{
|
||||
int64_t size_l = map_l != NULL ? map__size(map_l) : 0;
|
||||
int64_t size_r = map_r != NULL ? map__size(map_r) : 0;
|
||||
|
||||
return size_l < size_r ? -1 :
|
||||
size_l == size_r ? 0 : 1;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
sort__dso_size_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||
{
|
||||
return _sort__dso_size_cmp(right->ms.map, left->ms.map);
|
||||
}
|
||||
|
||||
static int _hist_entry__dso_size_snprintf(struct map *map, char *bf,
|
||||
size_t bf_size, unsigned int width)
|
||||
{
|
||||
if (map && map->dso)
|
||||
return repsep_snprintf(bf, bf_size, "%*d", width,
|
||||
map__size(map));
|
||||
|
||||
return repsep_snprintf(bf, bf_size, "%*s", width, "unknown");
|
||||
}
|
||||
|
||||
static int hist_entry__dso_size_snprintf(struct hist_entry *he, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return _hist_entry__dso_size_snprintf(he->ms.map, bf, size, width);
|
||||
}
|
||||
|
||||
struct sort_entry sort_dso_size = {
|
||||
.se_header = "DSO size",
|
||||
.se_cmp = sort__dso_size_cmp,
|
||||
.se_snprintf = hist_entry__dso_size_snprintf,
|
||||
.se_width_idx = HISTC_DSO_SIZE,
|
||||
};
|
||||
|
||||
|
||||
struct sort_dimension {
|
||||
const char *name;
|
||||
|
@ -1569,6 +1609,7 @@ static struct sort_dimension common_sort_dimensions[] = {
|
|||
DIM(SORT_TRANSACTION, "transaction", sort_transaction),
|
||||
DIM(SORT_TRACE, "trace", sort_trace),
|
||||
DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size),
|
||||
DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size),
|
||||
DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id),
|
||||
};
|
||||
|
||||
|
|
|
@ -220,6 +220,7 @@ enum sort_type {
|
|||
SORT_TRANSACTION,
|
||||
SORT_TRACE,
|
||||
SORT_SYM_SIZE,
|
||||
SORT_DSO_SIZE,
|
||||
SORT_CGROUP_ID,
|
||||
|
||||
/* branch stack specific sort keys */
|
||||
|
|
Loading…
Reference in New Issue