17 #include <subcmd/parse-options.h> 24 #include <linux/kernel.h> 25 #include <linux/rbtree.h> 26 #include <linux/string.h> 84 struct rb_node *parent = NULL;
89 data = rb_entry(*node,
struct alloc_stat, node);
92 node = &(*node)->rb_right;
93 else if (ptr < data->ptr)
94 node = &(*node)->rb_left;
99 if (data && data->
ptr == ptr) {
104 data =
malloc(
sizeof(*data));
106 pr_err(
"%s: malloc failed\n", __func__);
115 rb_link_node(&data->
node, parent, node);
129 struct rb_node *parent = NULL;
134 data = rb_entry(*node,
struct alloc_stat, node);
137 node = &(*node)->rb_right;
138 else if (call_site < data->call_site)
139 node = &(*node)->rb_left;
144 if (data && data->
call_site == call_site) {
149 data =
malloc(
sizeof(*data));
151 pr_err(
"%s: malloc failed\n", __func__);
160 rb_link_node(&data->
node, parent, node);
202 static int ptr_cmp(
void *,
void *);
207 struct rb_root *
root,
210 struct rb_node *
node = root->rb_node;
217 data = rb_entry(node,
struct alloc_stat, node);
219 cmp = sort_fn(&key, data);
221 node = node->rb_left;
223 node = node->rb_right;
270 #define MAX_MIGRATE_TYPES 6 271 #define MAX_PAGE_ORDER 11 303 static int funcmp(
const void *a,
const void *b)
314 static int callcmp(
const void *a,
const void *b)
331 struct map *kernel_map;
333 struct rb_node *
node;
336 regex_t alloc_func_regex;
337 const char pattern[] =
"^_?_?(alloc|get_free|get_zeroed)_pages?";
339 ret = regcomp(&alloc_func_regex, pattern, REG_EXTENDED);
343 regerror(ret, &alloc_func_regex, err,
sizeof(err));
344 pr_err(
"Invalid regex: %s\n%s", pattern, err);
350 pr_err(
"cannot load kernel map\n");
355 if (regexec(&alloc_func_regex, sym->
name, 0, NULL, 0))
358 func = realloc(alloc_func_list,
368 alloc_func_list =
func;
374 regfree(&alloc_func_regex);
388 if (alloc_func_list == NULL) {
423 pr_debug2(
"unknown callsite: %"PRIx64
"\n", sample->
ip);
430 struct list_head list;
434 static LIST_HEAD(page_caller_sort_input);
440 struct rb_node *parent = NULL;
447 data = rb_entry(*node,
struct page_stat, node);
451 node = &parent->rb_left;
453 node = &parent->rb_right;
461 data =
zalloc(
sizeof(*data));
468 rb_link_node(&data->
node, parent, node);
489 struct rb_node *parent = NULL;
497 data = rb_entry(*node,
struct page_stat, node);
499 list_for_each_entry(sort, &page_alloc_sort_input,
list) {
500 cmp = sort->
cmp(pstat, data);
506 node = &parent->rb_left;
508 node = &parent->rb_right;
516 data =
zalloc(
sizeof(*data));
523 rb_link_node(&data->
node, parent, node);
544 struct rb_node *parent = NULL;
552 data = rb_entry(*node,
struct page_stat, node);
554 list_for_each_entry(sort, &page_caller_sort_input,
list) {
555 cmp = sort->
cmp(pstat, data);
561 node = &parent->rb_left;
563 node = &parent->rb_right;
571 data =
zalloc(
sizeof(*data));
578 rb_link_node(&data->
node, parent, node);
597 if (
use_pfn && pfn_or_page == -1UL)
599 if (!
use_pfn && pfn_or_page == 0)
613 static int gfpcmp(
const void *a,
const void *b)
622 static const struct {
626 {
"GFP_TRANSHUGE",
"THP" },
627 {
"GFP_TRANSHUGE_LIGHT",
"THL" },
628 {
"GFP_HIGHUSER_MOVABLE",
"HUM" },
629 {
"GFP_HIGHUSER",
"HU" },
631 {
"GFP_KERNEL_ACCOUNT",
"KAC" },
632 {
"GFP_KERNEL",
"K" },
633 {
"GFP_NOFS",
"NF" },
634 {
"GFP_ATOMIC",
"A" },
635 {
"GFP_NOIO",
"NI" },
636 {
"GFP_NOWAIT",
"NW" },
638 {
"__GFP_HIGHMEM",
"HM" },
639 {
"GFP_DMA32",
"D32" },
640 {
"__GFP_HIGH",
"H" },
641 {
"__GFP_ATOMIC",
"_A" },
644 {
"__GFP_NOWARN",
"NWR" },
645 {
"__GFP_RETRY_MAYFAIL",
"R" },
646 {
"__GFP_NOFAIL",
"NF" },
647 {
"__GFP_NORETRY",
"NR" },
648 {
"__GFP_COMP",
"C" },
649 {
"__GFP_ZERO",
"Z" },
650 {
"__GFP_NOMEMALLOC",
"NMA" },
651 {
"__GFP_MEMALLOC",
"MA" },
652 {
"__GFP_HARDWALL",
"HW" },
653 {
"__GFP_THISNODE",
"TN" },
654 {
"__GFP_RECLAIMABLE",
"RC" },
655 {
"__GFP_MOVABLE",
"M" },
656 {
"__GFP_ACCOUNT",
"AC" },
657 {
"__GFP_WRITE",
"WR" },
658 {
"__GFP_RECLAIM",
"R" },
659 {
"__GFP_DIRECT_RECLAIM",
"DR" },
660 {
"__GFP_KSWAPD_RECLAIM",
"KR" },
667 char *orig_flags = strdup(gfp_flags);
668 char *new_flags = NULL;
669 char *
str, *pos = NULL;
672 if (orig_flags == NULL)
675 str = strtok_r(orig_flags,
"|", &pos);
686 new = realloc(new_flags, len + strlen(cpt) + 2);
695 strcpy(new_flags, cpt);
697 strcat(new_flags,
"|");
698 strcat(new_flags, cpt);
705 str = strtok_r(NULL,
"|", &pos);
730 unsigned int gfp_flags)
732 struct pevent_record record = {
737 struct trace_seq seq;
738 char *
str, *pos = NULL;
749 trace_seq_init(&seq);
750 pevent_event_info(&seq, evsel->
tp_format, &record);
752 str = strtok_r(seq.buffer,
" ", &pos);
754 if (!strncmp(str,
"gfp_flags=", 10)) {
757 new = realloc(gfps, (
nr_gfps + 1) *
sizeof(*gfps));
764 new->flags = gfp_flags;
765 new->human_readable = strdup(str + 10);
767 if (!
new->human_readable || !
new->compact_str)
773 str = strtok_r(NULL,
" ", &pos);
776 trace_seq_destroy(&seq);
875 pr_debug2(
"missing free at page %"PRIx64
" (order: %d)\n",
944 if (thread == NULL) {
945 pr_debug(
"problem processing %d event, skipping it.\n",
957 err =
f(evsel, sample);
971 .ordered_events =
true,
979 return 100.0 - (100.0 * n_req / n_alloc);
984 int n_lines,
int is_caller)
986 struct rb_node *next;
990 printf(
" %-34s |", is_caller ?
"Callsite":
"Alloc Ptr");
991 printf(
" Total_alloc/Per | Total_req/Per | Hit | Ping-pong | Frag\n");
994 next = rb_first(root);
996 while (next && n_lines--) {
1012 snprintf(buf,
sizeof(buf),
"%s+%" PRIx64
"", sym->
name,
1015 snprintf(buf,
sizeof(buf),
"%#" PRIx64
"", addr);
1016 printf(
" %-34s |", buf);
1018 printf(
" %9llu/%-5lu | %9llu/%-5lu | %8lu | %9lu | %6.3f%%\n",
1023 (
unsigned long)data->
hit,
1027 next = rb_next(next);
1031 printf(
" ... | ... | ... | ... | ... | ... \n");
1050 int gfp_len = max(strlen(
"GFP flags"),
max_gfp_len);
1053 printf(
" %-16s | %5s alloc (KB) | Hits | Order | Mig.type | %-*s | Callsite\n",
1055 gfp_len,
"GFP flags");
1059 format =
" %16llu | %'16llu | %'9d | %5d | %8s | %-*s | %s\n";
1061 format =
" %016llx | %'16llu | %'9d | %5d | %8s | %-*s | %s\n";
1063 while (next && n_lines--) {
1075 scnprintf(buf,
sizeof(buf),
"%"PRIx64, data->
callsite);
1077 printf(format, (
unsigned long long)data->
page,
1083 next = rb_next(next);
1086 if (n_lines == -1) {
1087 printf(
" ... | ... | ... | ... | ... | %-*s | ...\n",
1098 int gfp_len = max(strlen(
"GFP flags"),
max_gfp_len);
1101 printf(
" %5s alloc (KB) | Hits | Order | Mig.type | %-*s | Callsite\n",
1102 live_page ?
"Live" :
"Total", gfp_len,
"GFP flags");
1105 while (next && n_lines--) {
1117 scnprintf(buf,
sizeof(buf),
"%"PRIx64, data->
callsite);
1119 printf(
" %'16llu | %'9d | %5d | %8s | %-*s | %s\n",
1125 next = rb_next(next);
1128 if (n_lines == -1) {
1129 printf(
" ... | ... | ... | ... | %-*s | ...\n",
1141 printf(
"# GFP flags\n");
1142 printf(
"# ---------\n");
1143 for (i = 0; i <
nr_gfps; i++) {
1144 printf(
"# %08x: %*s: %s\n", gfps[i].
flags,
1146 gfps[i].human_readable);
1152 printf(
"\nSUMMARY (SLAB allocator)");
1153 printf(
"\n========================\n");
1158 printf(
"Net total bytes allocated: %'lu\n",
1161 printf(
"Total bytes wasted on internal fragmentation: %'lu\n",
1163 printf(
"Internal fragmentation: %f%%\n",
1174 printf(
"\nSUMMARY (page allocator)");
1175 printf(
"\n========================\n");
1176 printf(
"%-30s: %'16lu [ %'16"PRIu64
" KB ]\n",
"Total allocation requests",
1178 printf(
"%-30s: %'16lu [ %'16"PRIu64
" KB ]\n",
"Total free requests",
1182 printf(
"%-30s: %'16"PRIu64
" [ %'16"PRIu64
" KB ]\n",
"Total alloc+freed requests",
1183 nr_alloc_freed, (total_alloc_freed_bytes) / 1024);
1184 printf(
"%-30s: %'16"PRIu64
" [ %'16"PRIu64
" KB ]\n",
"Total alloc-only requests",
1187 printf(
"%-30s: %'16lu [ %'16"PRIu64
" KB ]\n",
"Total free-only requests",
1188 nr_page_nomatch, total_page_nomatch_bytes / 1024);
1191 printf(
"%-30s: %'16lu [ %'16"PRIu64
" KB ]\n",
"Total allocation failures",
1195 printf(
"%5s %12s %12s %12s %12s %12s\n",
"Order",
"Unmovable",
1196 "Reclaimable",
"Movable",
"Reserved",
"CMA/Isolated");
1207 printf(
" %12c",
'.');
1247 struct list_head *sort_list)
1249 struct rb_node **
new = &(root->rb_node);
1250 struct rb_node *parent = NULL;
1260 list_for_each_entry(sort, sort_list, list) {
1261 cmp = sort->
cmp(data,
this);
1267 new = &((*new)->rb_left);
1269 new = &((*new)->rb_right);
1272 rb_link_node(&data->
node, parent,
new);
1273 rb_insert_color(&data->
node, root);
1277 struct list_head *sort_list)
1279 struct rb_node *
node;
1283 node = rb_first(root);
1287 rb_erase(node, root);
1288 data = rb_entry(node,
struct alloc_stat, node);
1294 struct list_head *sort_list)
1296 struct rb_node **
new = &root->rb_node;
1297 struct rb_node *parent = NULL;
1307 list_for_each_entry(sort, sort_list, list) {
1308 cmp = sort->
cmp(data,
this);
1314 new = &parent->rb_left;
1316 new = &parent->rb_right;
1319 rb_link_node(&data->
node, parent,
new);
1320 rb_insert_color(&data->
node, root);
1324 struct list_head *sort_list)
1326 struct rb_node *
node;
1330 node = rb_first(root);
1334 rb_erase(node, root);
1335 data = rb_entry(node,
struct page_stat, node);
1382 pr_err(
"Initializing perf session tracepoint handlers failed\n");
1397 pr_err(
"error during process events: %d\n", err);
1414 else if (l->
ptr > r->
ptr)
1448 else if (l->
hit > r->
hit)
1665 for (i = 0; i < (int)ARRAY_SIZE(slab_sorts); i++) {
1666 if (!strcmp(slab_sorts[i]->
name, tok)) {
1667 sort = memdup(slab_sorts[i],
sizeof(*slab_sorts[i]));
1669 pr_err(
"%s: memdup failed\n", __func__);
1672 list_add_tail(&sort->
list, list);
1685 for (i = 0; i < (int)ARRAY_SIZE(page_sorts); i++) {
1686 if (!strcmp(page_sorts[i]->
name, tok)) {
1687 sort = memdup(page_sorts[i],
sizeof(*page_sorts[i]));
1689 pr_err(
"%s: memdup failed\n", __func__);
1692 list_add_tail(&sort->
list, list);
1703 char *
str = strdup(arg);
1707 pr_err(
"%s: strdup failed\n", __func__);
1712 tok = strsep(&pos,
",");
1716 pr_err(
"Unknown slab --sort key: '%s'", tok);
1729 char *
str = strdup(arg);
1733 pr_err(
"%s: strdup failed\n", __func__);
1738 tok = strsep(&pos,
",");
1742 pr_err(
"Unknown page --sort key: '%s'", tok);
1753 const char *arg,
int unset __maybe_unused)
1775 const char *arg __maybe_unused,
1776 int unset __maybe_unused)
1783 const char *arg __maybe_unused,
1784 int unset __maybe_unused)
1791 const char *arg __maybe_unused,
1792 int unset __maybe_unused)
1799 const char *arg __maybe_unused,
1800 int unset __maybe_unused)
1807 const char *arg,
int unset __maybe_unused)
1814 lines = strtoul(arg, NULL, 10);
1826 const char *
const record_args[] = {
1827 "record",
"-a",
"-R",
"-c",
"1",
1829 const char *
const slab_events[] = {
1830 "-e",
"kmem:kmalloc",
1831 "-e",
"kmem:kmalloc_node",
1833 "-e",
"kmem:kmem_cache_alloc",
1834 "-e",
"kmem:kmem_cache_alloc_node",
1835 "-e",
"kmem:kmem_cache_free",
1837 const char *
const page_events[] = {
1838 "-e",
"kmem:mm_page_alloc",
1839 "-e",
"kmem:mm_page_free",
1841 unsigned int rec_argc, i, j;
1842 const char **rec_argv;
1844 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
1846 rec_argc += ARRAY_SIZE(slab_events);
1848 rec_argc += ARRAY_SIZE(page_events) + 1;
1850 rec_argv = calloc(rec_argc + 1,
sizeof(
char *));
1852 if (rec_argv == NULL)
1855 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1856 rec_argv[i] = strdup(record_args[i]);
1859 for (j = 0; j < ARRAY_SIZE(slab_events); j++, i++)
1860 rec_argv[i] = strdup(slab_events[j]);
1863 rec_argv[i++] = strdup(
"-g");
1865 for (j = 0; j < ARRAY_SIZE(page_events); j++, i++)
1866 rec_argv[i] = strdup(page_events[j]);
1869 for (j = 1; j < (
unsigned int)argc; j++, i++)
1870 rec_argv[i] = argv[j];
1877 if (!strcmp(var,
"kmem.default")) {
1878 if (!strcmp(value,
"slab"))
1880 else if (!strcmp(value,
"page"))
1883 pr_err(
"invalid default value ('slab' or 'page' required): %s\n",
1893 const char *
const default_slab_sort =
"frag,hit,bytes";
1894 const char *
const default_page_sort =
"bytes,hit";
1898 const struct option kmem_options[] = {
1899 OPT_STRING(
'i',
"input", &
input_name,
"file",
"input file name"),
1900 OPT_INCR(
'v',
"verbose", &
verbose,
1901 "be more verbose (show symbol address, etc)"),
1902 OPT_CALLBACK_NOOPT(0,
"caller", NULL, NULL,
1904 OPT_CALLBACK_NOOPT(0,
"alloc", NULL, NULL,
1906 OPT_CALLBACK(
's',
"sort", NULL,
"key[,key2...]",
1907 "sort by keys: ptr, callsite, bytes, hit, pingpong, frag, " 1909 OPT_CALLBACK(
'l',
"line", NULL,
"num",
"show n lines",
parse_line_opt),
1910 OPT_BOOLEAN(0,
"raw-ip", &
raw_ip,
"show raw ip instead of symbol"),
1911 OPT_BOOLEAN(
'f',
"force", &data.
force,
"don't complain, do it"),
1912 OPT_CALLBACK_NOOPT(0,
"slab", NULL, NULL,
"Analyze slab allocator",
1914 OPT_CALLBACK_NOOPT(0,
"page", NULL, NULL,
"Analyze page allocator",
1916 OPT_BOOLEAN(0,
"live", &
live_page,
"Show live page stat"),
1917 OPT_STRING(0,
"time", &
time_str,
"str",
1918 "Time span of interest (start,stop)"),
1921 const char *
const kmem_subcommands[] = {
"record",
"stat", NULL };
1922 const char *kmem_usage[] = {
1927 const char errmsg[] =
"No %s allocation events found. Have you run 'perf kmem record --%s'?\n";
1933 argc = parse_options_subcommand(argc, argv, kmem_options,
1934 kmem_subcommands, kmem_usage, 0);
1937 usage_with_options(kmem_usage, kmem_options);
1946 if (!strncmp(argv[0],
"rec", 3)) {
1954 if (session == NULL)
1962 pr_err(errmsg,
"slab",
"slab");
1971 "kmem:mm_page_alloc");
1972 if (evsel == NULL) {
1973 pr_err(errmsg,
"page",
"page");
1984 pr_err(
"Invalid time string\n");
1989 if (!strcmp(argv[0],
"stat")) {
1990 setlocale(LC_ALL,
"");
1995 if (list_empty(&slab_caller_sort))
1997 if (list_empty(&slab_alloc_sort))
1999 if (list_empty(&page_caller_sort))
2001 if (list_empty(&page_alloc_sort))
2006 "page,order,migtype,gfp");
2008 "callsite,order,migtype,gfp");
2012 usage_with_options(kmem_usage, kmem_options);
static struct page_stat * page_stat__find_page(struct page_stat *pstat)
static int funcmp(const void *a, const void *b)
#define MAX_MIGRATE_TYPES
struct perf_evlist * evlist
static int perf_evsel__process_alloc_event(struct perf_evsel *evsel, struct perf_sample *sample)
static u64 map__unmap_ip(struct map *map, u64 ip)
static int callcmp(const void *a, const void *b)
static int process_sample_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine)
int(* sort_fn_t)(void *, void *)
static int nr_alloc_funcs
static int slab_sort_dimension__add(const char *tok, struct list_head *list)
static unsigned long nr_page_nomatch
static LIST_HEAD(page_alloc_sort_input)
static bool valid_page(u64 pfn_or_page)
int cmd_record(int argc, const char **argv)
static int page_order_cmp(void *a, void *b)
int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static int bytes_cmp(void *a, void *b)
const char * graph_dotted_line
static struct sort_dimension * slab_sorts[]
static struct perf_time_interval ptime
static struct sort_dimension callsite_sort_dimension
static int parse_alloc_opt(const struct option *opt __maybe_unused, const char *arg __maybe_unused, int unset __maybe_unused)
static char * compact_gfp_string(unsigned long gfp_flags)
static struct rb_root root_caller_sorted
static struct sort_dimension page_sort_dimension
static void print_gfp_flags(void)
static int build_alloc_func_list(void)
#define map__for_each_symbol(map, pos, n)
static struct page_stat * page_stat__find_alloc(struct page_stat *pstat)
static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample, unsigned int gfp_flags)
struct perf_data_file file
int cpu__get_node(int cpu)
static bool perf_kmem__skip_sample(struct perf_sample *sample)
#define pr_debug2(fmt,...)
static struct sort_dimension pingpong_sort_dimension
static char * compact_gfp_flags(char *gfp_flags)
static struct rb_root page_live_tree
static int perf_evsel__process_page_free_event(struct perf_evsel *evsel, struct perf_sample *sample)
static void print_page_summary(void)
int perf_event__process_comm(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static struct alloc_func * alloc_func_list
static struct rb_root root_alloc_sorted
static void callchain_cursor_commit(struct callchain_cursor *cursor)
static int gfp_flags_cmp(void *a, void *b)
static int parse_page_opt(const struct option *opt __maybe_unused, const char *arg __maybe_unused, int unset __maybe_unused)
int dump_printf(const char *fmt,...)
static size_t max_gfp_len
bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp)
static const char *const migrate_type_str[]
static struct perf_tool perf_kmem
static void print_slab_result(struct perf_session *session)
static void sort_result(void)
bool perf_session__has_traces(struct perf_session *session, const char *msg)
static int ptr_cmp(void *, void *)
static int perf_evsel__process_alloc_node_event(struct perf_evsel *evsel, struct perf_sample *sample)
void perf_session__delete(struct perf_session *session)
static int perf_evsel__process_free_event(struct perf_evsel *evsel, struct perf_sample *sample)
static struct sort_dimension bytes_sort_dimension
static int parse_line_opt(const struct option *opt __maybe_unused, const char *arg, int unset __maybe_unused)
int sample__resolve_callchain(struct perf_sample *sample, struct callchain_cursor *cursor, struct symbol **parent, struct perf_evsel *evsel, struct addr_location *al, int max_stack)
static int parse_slab_opt(const struct option *opt __maybe_unused, const char *arg __maybe_unused, int unset __maybe_unused)
static struct rb_root page_alloc_sorted
static unsigned long total_freed
static struct map * machine__kernel_map(struct machine *machine)
int cmd_kmem(int argc, const char **argv)
static void print_result(struct perf_session *session)
static void __sort_page_result(struct rb_root *root, struct rb_root *root_sorted, struct list_head *sort_list)
const char * thread__comm_str(const struct thread *thread)
static enum @5 kmem_default
static int __cmd_record(int argc, const char **argv)
#define pr_debug(fmt,...)
static long kmem_page_size
static struct gfp_flag * gfps
static struct perf_session * session
static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel, struct perf_sample *sample)
static int hit_cmp(void *a, void *b)
#define evlist__for_each_entry(evlist, evsel)
static struct page_stat * page_stat__findnew_caller(struct page_stat *pstat)
static void callchain_cursor_advance(struct callchain_cursor *cursor)
static void print_page_result(struct perf_session *session)
static struct rb_root root_alloc_stat
static struct perf_session * kmem_session
static int migrate_type_cmp(void *a, void *b)
static void __print_slab_result(struct rb_root *root, struct perf_session *session, int n_lines, int is_caller)
static u64 total_page_free_bytes
static struct rb_root page_alloc_tree
static int page_bytes_cmp(void *a, void *b)
static void sort_slab_insert(struct rb_root *root, struct alloc_stat *data, struct list_head *sort_list)
static u64 total_page_nomatch_bytes
static struct alloc_stat * search_alloc_stat(unsigned long ptr, unsigned long call_site, struct rb_root *root, sort_fn_t sort_fn)
static struct perf_tool tool
struct event_format * tp_format
static int setup_page_sorting(struct list_head *sort_list, const char *arg)
static int str(yyscan_t scanner, int token)
static struct sort_dimension * page_sorts[]
static double fragmentation(unsigned long n_req, unsigned long n_alloc)
static u64 find_callsite(struct perf_evsel *evsel, struct perf_sample *sample)
static int order_stats[MAX_PAGE_ORDER][MAX_MIGRATE_TYPES]
static struct rb_root root_caller_stat
static int parse_sort_opt(const struct option *opt __maybe_unused, const char *arg, int unset __maybe_unused)
u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, const char *name)
static struct page_stat * __page_stat__findnew_page(struct page_stat *pstat, bool create)
static const struct @6 gfp_compact_table[]
static int parse_caller_opt(const struct option *opt __maybe_unused, const char *arg __maybe_unused, int unset __maybe_unused)
static void __print_page_caller_result(struct perf_session *session, int n_lines)
static int __cmd_kmem(struct perf_session *session)
static struct sort_dimension page_order_sort_dimension
static void __sort_slab_result(struct rb_root *root, struct rb_root *root_sorted, struct list_head *sort_list)
const char * perf_evsel__name(struct perf_evsel *evsel)
static struct page_stat * __page_stat__findnew_alloc(struct page_stat *pstat, bool create)
static struct sort_dimension gfp_flags_sort_dimension
static int pingpong_cmp(void *a, void *b)
struct perf_event_header header
static int page_cmp(void *a, void *b)
static struct page_stat * page_stat__find_caller(struct page_stat *pstat)
struct perf_session * perf_session__new(struct perf_data *data, bool repipe, struct perf_tool *tool)
static void print_slab_summary(void)
int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static int kmem_config(const char *var, const char *value, void *cb __maybe_unused)
static unsigned long nr_page_allocs
static unsigned long nr_page_fails
static void __print_page_alloc_result(struct perf_session *session, int n_lines)
void thread__put(struct thread *thread)
static unsigned long nr_allocs
static struct sort_dimension hit_sort_dimension
static void sort_page_insert(struct rb_root *root, struct page_stat *data, struct list_head *sort_list)
static struct sort_dimension migrate_type_sort_dimension
int perf_config(config_fn_t fn, void *data)
int perf_session__process_events(struct perf_session *session)
static int sym(yyscan_t scanner, int type, int config)
static struct sort_dimension page_bytes_sort_dimension
struct perf_evsel * perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, const char *name)
static unsigned long total_allocated
static int page_hit_cmp(void *a, void *b)
struct perf_header header
static int setup_slab_sorting(struct list_head *sort_list, const char *arg)
int symbol__init(struct perf_env *env)
static struct symbol * machine__find_kernel_symbol(struct machine *machine, u64 addr, struct map **mapp)
static unsigned long nr_cross_allocs
static unsigned long nr_page_frees
static int slab_callsite_cmp(void *, void *)
static struct rb_root page_caller_sorted
static int page_callsite_cmp(void *a, void *b)
static struct page_stat * __page_stat__findnew_caller(struct page_stat *pstat, bool create)
static int insert_alloc_stat(unsigned long call_site, unsigned long ptr, int bytes_req, int bytes_alloc, int cpu)
static struct sort_dimension frag_sort_dimension
u64(* unmap_ip)(struct map *, u64)
static int page_sort_dimension__add(const char *tok, struct list_head *list)
static struct rb_root page_caller_tree
static unsigned long total_requested
#define perf_session__set_tracepoints_handlers(session, array)
int(* tracepoint_handler)(struct perf_evsel *evsel, struct perf_sample *sample)
int cpu__setup_cpunode_map(void)
struct format_field * perf_evsel__field(struct perf_evsel *evsel, const char *name)
int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
int map__load(struct map *map)
static struct sort_dimension ptr_sort_dimension
static struct page_stat * page_stat__findnew_alloc(struct page_stat *pstat)
static u64 total_page_alloc_bytes
static int frag_cmp(void *a, void *b)
#define pr_debug3(fmt,...)
static int gfpcmp(const void *a, const void *b)
struct thread * machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid)
int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr)
static struct sort_dimension page_hit_sort_dimension
static struct sort_dimension page_callsite_sort_dimension
static struct callchain_cursor_node * callchain_cursor_current(struct callchain_cursor *cursor)
static struct page_stat * page_stat__findnew_page(struct page_stat *pstat)
void static void * zalloc(size_t size)
static u64 total_page_fail_bytes
static int insert_caller_stat(unsigned long call_site, int bytes_req, int bytes_alloc)