Commit 7d0d3945 authored by Li Zefan's avatar Li Zefan Committed by Ingo Molnar

perf kmem: Collect cross node allocation statistics

Show cross node memory allocations:

 # ./perf kmem

 SUMMARY
 =======
 ...
 Cross node allocations: 0/3633
Signed-off-by: default avatarLi Zefan <lizf@cn.fujitsu.com>
Acked-by: default avatarPekka Enberg <penberg@cs.helsinki.fi>
Cc: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: linux-mm@kvack.org <linux-mm@kvack.org>
LKML-Reference: <4B0B6E87.10906@cn.fujitsu.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 29b3e152
...@@ -36,6 +36,9 @@ static char default_sort_order[] = "frag,hit,bytes"; ...@@ -36,6 +36,9 @@ static char default_sort_order[] = "frag,hit,bytes";
static char *cwd; static char *cwd;
static int cwdlen; static int cwdlen;
static int *cpunode_map;
static int max_cpu_num;
struct alloc_stat { struct alloc_stat {
union { union {
u64 call_site; u64 call_site;
...@@ -54,12 +57,74 @@ static struct rb_root root_caller_stat; ...@@ -54,12 +57,74 @@ static struct rb_root root_caller_stat;
static struct rb_root root_caller_sorted; static struct rb_root root_caller_sorted;
static unsigned long total_requested, total_allocated; static unsigned long total_requested, total_allocated;
static unsigned long nr_allocs, nr_cross_allocs;
struct raw_event_sample { struct raw_event_sample {
u32 size; u32 size;
char data[0]; char data[0];
}; };
#define PATH_SYS_NODE "/sys/devices/system/node"
static void init_cpunode_map(void)
{
FILE *fp;
int i;
fp = fopen("/sys/devices/system/cpu/kernel_max", "r");
if (!fp) {
max_cpu_num = 4096;
return;
}
if (fscanf(fp, "%d", &max_cpu_num) < 1)
die("Failed to read 'kernel_max' from sysfs");
max_cpu_num++;
cpunode_map = calloc(max_cpu_num, sizeof(int));
if (!cpunode_map)
die("calloc");
for (i = 0; i < max_cpu_num; i++)
cpunode_map[i] = -1;
fclose(fp);
}
static void setup_cpunode_map(void)
{
struct dirent *dent1, *dent2;
DIR *dir1, *dir2;
unsigned int cpu, mem;
char buf[PATH_MAX];
init_cpunode_map();
dir1 = opendir(PATH_SYS_NODE);
if (!dir1)
return;
while (true) {
dent1 = readdir(dir1);
if (!dent1)
break;
if (sscanf(dent1->d_name, "node%u", &mem) < 1)
continue;
snprintf(buf, PATH_MAX, "%s/%s", PATH_SYS_NODE, dent1->d_name);
dir2 = opendir(buf);
if (!dir2)
continue;
while (true) {
dent2 = readdir(dir2);
if (!dent2)
break;
if (sscanf(dent2->d_name, "cpu%u", &cpu) < 1)
continue;
cpunode_map[cpu] = mem;
}
}
}
static int static int
process_comm_event(event_t *event, unsigned long offset, unsigned long head) process_comm_event(event_t *event, unsigned long offset, unsigned long head)
{ {
...@@ -157,15 +222,16 @@ static void insert_caller_stat(unsigned long call_site, ...@@ -157,15 +222,16 @@ static void insert_caller_stat(unsigned long call_site,
static void process_alloc_event(struct raw_event_sample *raw, static void process_alloc_event(struct raw_event_sample *raw,
struct event *event, struct event *event,
int cpu __used, int cpu,
u64 timestamp __used, u64 timestamp __used,
struct thread *thread __used, struct thread *thread __used,
int node __used) int node)
{ {
unsigned long call_site; unsigned long call_site;
unsigned long ptr; unsigned long ptr;
int bytes_req; int bytes_req;
int bytes_alloc; int bytes_alloc;
int node1, node2;
ptr = raw_field_value(event, "ptr", raw->data); ptr = raw_field_value(event, "ptr", raw->data);
call_site = raw_field_value(event, "call_site", raw->data); call_site = raw_field_value(event, "call_site", raw->data);
...@@ -177,6 +243,14 @@ static void process_alloc_event(struct raw_event_sample *raw, ...@@ -177,6 +243,14 @@ static void process_alloc_event(struct raw_event_sample *raw,
total_requested += bytes_req; total_requested += bytes_req;
total_allocated += bytes_alloc; total_allocated += bytes_alloc;
if (node) {
node1 = cpunode_map[cpu];
node2 = raw_field_value(event, "node", raw->data);
if (node1 != node2)
nr_cross_allocs++;
}
nr_allocs++;
} }
static void process_free_event(struct raw_event_sample *raw __used, static void process_free_event(struct raw_event_sample *raw __used,
...@@ -359,6 +433,7 @@ static void print_summary(void) ...@@ -359,6 +433,7 @@ static void print_summary(void)
total_allocated - total_requested); total_allocated - total_requested);
printf("Internal fragmentation: %f%%\n", printf("Internal fragmentation: %f%%\n",
fragmentation(total_requested, total_allocated)); fragmentation(total_requested, total_allocated));
printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs);
} }
static void print_result(void) static void print_result(void)
...@@ -685,6 +760,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __used) ...@@ -685,6 +760,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __used)
if (list_empty(&alloc_sort)) if (list_empty(&alloc_sort))
setup_sorting(&alloc_sort, default_sort_order); setup_sorting(&alloc_sort, default_sort_order);
setup_cpunode_map();
return __cmd_kmem(); return __cmd_kmem();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment