1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "builtin.h" 2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "perf.h" 3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util/util.h" 5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util/cache.h" 6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util/symbol.h" 7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util/thread.h" 8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util/header.h" 9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util/session.h" 10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util/parse-options.h" 12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util/trace-event.h" 13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util/debug.h" 15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* ANDROID_CHANGE_BEGIN */ 17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#if 0 18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <linux/rbtree.h> 19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#else 20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util/include/linux/rbtree.h" 21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif 22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* ANDROID_CHANGE_END */ 23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct alloc_stat; 25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengtypedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); 26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic char const *input_name = "perf.data"; 28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int alloc_flag; 30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int caller_flag; 31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int alloc_lines = -1; 33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int caller_lines = -1; 34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic bool raw_ip; 36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic char default_sort_order[] = "frag,hit,bytes"; 38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int *cpunode_map; 40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int max_cpu_num; 41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct alloc_stat { 43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 call_site; 44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 ptr; 45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 bytes_req; 46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 bytes_alloc; 47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u32 hit; 48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u32 pingpong; 49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng short alloc_cpu; 51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node node; 53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct rb_root root_alloc_stat; 56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct rb_root root_alloc_sorted; 57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct rb_root root_caller_stat; 58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct rb_root root_caller_sorted; 59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic unsigned long total_requested, total_allocated; 61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic unsigned long nr_allocs, nr_cross_allocs; 62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define PATH_SYS_NODE "/sys/devices/system/node" 64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void init_cpunode_map(void) 66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng FILE *fp; 68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i; 69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fp = fopen("/sys/devices/system/cpu/kernel_max", "r"); 71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!fp) { 72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng max_cpu_num = 4096; 73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fscanf(fp, "%d", &max_cpu_num) < 1) 77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng die("Failed to read 'kernel_max' from sysfs"); 78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng max_cpu_num++; 79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cpunode_map = calloc(max_cpu_num, sizeof(int)); 81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!cpunode_map) 82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng die("calloc"); 83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < max_cpu_num; i++) 84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cpunode_map[i] = -1; 85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fclose(fp); 86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void setup_cpunode_map(void) 89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dirent *dent1, *dent2; 91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng DIR *dir1, *dir2; 92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int cpu, mem; 93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[PATH_MAX]; 94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng init_cpunode_map(); 96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dir1 = opendir(PATH_SYS_NODE); 98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!dir1) 99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while ((dent1 = readdir(dir1)) != NULL) { 102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dent1->d_type != DT_DIR || 103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sscanf(dent1->d_name, "node%u", &mem) < 1) 104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(buf, PATH_MAX, "%s/%s", PATH_SYS_NODE, dent1->d_name); 107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dir2 = opendir(buf); 108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!dir2) 109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while ((dent2 = readdir(dir2)) != NULL) { 111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dent2->d_type != DT_LNK || 112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sscanf(dent2->d_name, "cpu%u", &cpu) < 1) 113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cpunode_map[cpu] = mem; 115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void insert_alloc_stat(unsigned long call_site, unsigned long ptr, 120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int bytes_req, int bytes_alloc, int cpu) 121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node **node = &root_alloc_stat.rb_node; 123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *parent = NULL; 124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct alloc_stat *data = NULL; 125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*node) { 127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parent = *node; 128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data = rb_entry(*node, struct alloc_stat, node); 129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ptr > data->ptr) 131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node = &(*node)->rb_right; 132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (ptr < data->ptr) 133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node = &(*node)->rb_left; 134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (data && data->ptr == ptr) { 139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->hit++; 140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->bytes_req += bytes_req; 141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->bytes_alloc += bytes_alloc; 142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { 143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data = malloc(sizeof(*data)); 144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!data) 145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng die("malloc"); 146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->ptr = ptr; 147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->pingpong = 0; 148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->hit = 1; 149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->bytes_req = bytes_req; 150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->bytes_alloc = bytes_alloc; 151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_link_node(&data->node, parent, node); 153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_insert_color(&data->node, &root_alloc_stat); 154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->call_site = call_site; 156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->alloc_cpu = cpu; 157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void insert_caller_stat(unsigned long call_site, 160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int bytes_req, int bytes_alloc) 161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node **node = &root_caller_stat.rb_node; 163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *parent = NULL; 164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct alloc_stat *data = NULL; 165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*node) { 167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parent = *node; 168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data = rb_entry(*node, struct alloc_stat, node); 169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (call_site > data->call_site) 171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node = &(*node)->rb_right; 172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (call_site < data->call_site) 173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node = &(*node)->rb_left; 174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (data && data->call_site == call_site) { 179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->hit++; 180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->bytes_req += bytes_req; 181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->bytes_alloc += bytes_alloc; 182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { 183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data = malloc(sizeof(*data)); 184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!data) 185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng die("malloc"); 186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->call_site = call_site; 187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->pingpong = 0; 188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->hit = 1; 189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->bytes_req = bytes_req; 190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data->bytes_alloc = bytes_alloc; 191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_link_node(&data->node, parent, node); 193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_insert_color(&data->node, &root_caller_stat); 194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void process_alloc_event(void *data, 198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct event *event, 199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int cpu, 200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 timestamp __used, 201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct thread *thread __used, 202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int node) 203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned long call_site; 205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned long ptr; 206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int bytes_req; 207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int bytes_alloc; 208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int node1, node2; 209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ptr = raw_field_value(event, "ptr", data); 211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng call_site = raw_field_value(event, "call_site", data); 212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng bytes_req = raw_field_value(event, "bytes_req", data); 213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng bytes_alloc = raw_field_value(event, "bytes_alloc", data); 214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, cpu); 216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng insert_caller_stat(call_site, bytes_req, bytes_alloc); 217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng total_requested += bytes_req; 219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng total_allocated += bytes_alloc; 220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (node) { 222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node1 = cpunode_map[cpu]; 223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node2 = raw_field_value(event, "node", data); 224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (node1 != node2) 225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng nr_cross_allocs++; 226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng nr_allocs++; 228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int ptr_cmp(struct alloc_stat *, struct alloc_stat *); 231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int callsite_cmp(struct alloc_stat *, struct alloc_stat *); 232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct alloc_stat *search_alloc_stat(unsigned long ptr, 234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned long call_site, 235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_root *root, 236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sort_fn_t sort_fn) 237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *node = root->rb_node; 239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct alloc_stat key = { .ptr = ptr, .call_site = call_site }; 240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (node) { 242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct alloc_stat *data; 243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int cmp; 244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data = rb_entry(node, struct alloc_stat, node); 246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmp = sort_fn(&key, data); 248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmp < 0) 249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node = node->rb_left; 250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmp > 0) 251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node = node->rb_right; 252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return data; 254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void process_free_event(void *data, 259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct event *event, 260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int cpu, 261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 timestamp __used, 262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct thread *thread __used) 263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned long ptr; 265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct alloc_stat *s_alloc, *s_caller; 266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ptr = raw_field_value(event, "ptr", data); 268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp); 270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!s_alloc) 271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cpu != s_alloc->alloc_cpu) { 274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng s_alloc->pingpong++; 275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng s_caller = search_alloc_stat(0, s_alloc->call_site, 277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &root_caller_stat, callsite_cmp); 278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng assert(s_caller); 279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng s_caller->pingpong++; 280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng s_alloc->alloc_cpu = -1; 282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void process_raw_event(union perf_event *raw_event __used, void *data, 285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int cpu, u64 timestamp, struct thread *thread) 286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct event *event; 288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int type; 289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng type = trace_parse_common_type(data); 291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event = trace_find_event(type); 292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!strcmp(event->name, "kmalloc") || 294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng !strcmp(event->name, "kmem_cache_alloc")) { 295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process_alloc_event(data, event, cpu, timestamp, thread, 0); 296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!strcmp(event->name, "kmalloc_node") || 300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng !strcmp(event->name, "kmem_cache_alloc_node")) { 301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process_alloc_event(data, event, cpu, timestamp, thread, 1); 302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!strcmp(event->name, "kfree") || 306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng !strcmp(event->name, "kmem_cache_free")) { 307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process_free_event(data, event, cpu, timestamp, thread); 308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int process_sample_event(union perf_event *event, 313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_sample *sample, 314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_evsel *evsel __used, 315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct thread *thread = perf_session__findnew(session, event->ip.pid); 318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (thread == NULL) { 320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("problem processing %d event, skipping it.\n", 321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->header.type); 322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process_raw_event(event, sample->raw_data, sample->cpu, 328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sample->time, thread); 329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct perf_event_ops event_ops = { 334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .sample = process_sample_event, 335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .comm = perf_event__process_comm, 336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .ordered_samples = true, 337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic double fragmentation(unsigned long n_req, unsigned long n_alloc) 340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (n_alloc == 0) 342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0.0; 343e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 100.0 - (100.0 * n_req / n_alloc); 345e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 346e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 347e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void __print_result(struct rb_root *root, struct perf_session *session, 348e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int n_lines, int is_caller) 349e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 350e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *next; 351e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *machine; 352e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 353e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("%.102s\n", graph_dotted_line); 354e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr"); 355e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" Total_alloc/Per | Total_req/Per | Hit | Ping-pong | Frag\n"); 356e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("%.102s\n", graph_dotted_line); 357e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 358e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng next = rb_first(root); 359e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 360e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine = perf_session__find_host_machine(session); 361e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!machine) { 362e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("__print_result: couldn't find kernel information\n"); 363e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 364e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 365e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (next && n_lines--) { 366e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct alloc_stat *data = rb_entry(next, struct alloc_stat, 367e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node); 368e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct symbol *sym = NULL; 369e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *map; 370e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[BUFSIZ]; 371e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 addr; 372e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 373e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (is_caller) { 374e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng addr = data->call_site; 375e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!raw_ip) 376e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sym = machine__find_kernel_function(machine, addr, &map, NULL); 377e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else 378e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng addr = data->ptr; 379e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 380e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (sym != NULL) 381e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(buf, sizeof(buf), "%s+%" PRIx64 "", sym->name, 382e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng addr - map->unmap_ip(map, sym->start)); 383e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 384e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr); 385e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" %-34s |", buf); 386e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 387e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n", 388e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (unsigned long long)data->bytes_alloc, 389e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (unsigned long)data->bytes_alloc / data->hit, 390e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (unsigned long long)data->bytes_req, 391e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (unsigned long)data->bytes_req / data->hit, 392e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (unsigned long)data->hit, 393e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (unsigned long)data->pingpong, 394e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fragmentation(data->bytes_req, data->bytes_alloc)); 395e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 396e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng next = rb_next(next); 397e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 398e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 399e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (n_lines == -1) 400e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" ... | ... | ... | ... | ... | ... \n"); 401e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 402e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("%.102s\n", graph_dotted_line); 403e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 404e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 405e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void print_summary(void) 406e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 407e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("\nSUMMARY\n=======\n"); 408e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("Total bytes requested: %lu\n", total_requested); 409e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("Total bytes allocated: %lu\n", total_allocated); 410e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("Total bytes wasted on internal fragmentation: %lu\n", 411e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng total_allocated - total_requested); 412e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("Internal fragmentation: %f%%\n", 413e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fragmentation(total_requested, total_allocated)); 414e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs); 415e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 416e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 417e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void print_result(struct perf_session *session) 418e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 419e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (caller_flag) 420e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng __print_result(&root_caller_sorted, session, caller_lines, 1); 421e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (alloc_flag) 422e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng __print_result(&root_alloc_sorted, session, alloc_lines, 0); 423e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng print_summary(); 424e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 425e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 426e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct sort_dimension { 427e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char name[20]; 428e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sort_fn_t cmp; 429e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct list_head list; 430e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 431e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 432e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic LIST_HEAD(caller_sort); 433e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic LIST_HEAD(alloc_sort); 434e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 435e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void sort_insert(struct rb_root *root, struct alloc_stat *data, 436e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct list_head *sort_list) 437e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 438e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node **new = &(root->rb_node); 439e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *parent = NULL; 440e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct sort_dimension *sort; 441e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 442e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*new) { 443e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct alloc_stat *this; 444e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int cmp = 0; 445e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 446e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng this = rb_entry(*new, struct alloc_stat, node); 447e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parent = *new; 448e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 449e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry(sort, sort_list, list) { 450e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmp = sort->cmp(data, this); 451e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmp) 452e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 453e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 454e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 455e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmp > 0) 456e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng new = &((*new)->rb_left); 457e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 458e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng new = &((*new)->rb_right); 459e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 460e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 461e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_link_node(&data->node, parent, new); 462e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_insert_color(&data->node, root); 463e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 464e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 465e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void __sort_result(struct rb_root *root, struct rb_root *root_sorted, 466e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct list_head *sort_list) 467e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 468e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *node; 469e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct alloc_stat *data; 470e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 471e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (;;) { 472e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node = rb_first(root); 473e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!node) 474e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 475e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 476e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_erase(node, root); 477e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng data = rb_entry(node, struct alloc_stat, node); 478e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sort_insert(root_sorted, data, sort_list); 479e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 480e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 481e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 482e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void sort_result(void) 483e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 484e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng __sort_result(&root_alloc_stat, &root_alloc_sorted, &alloc_sort); 485e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 486e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 487e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 488e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __cmd_kmem(void) 489e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 490e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int err = -EINVAL; 491e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session = perf_session__new(input_name, O_RDONLY, 492e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 0, false, &event_ops); 493e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (session == NULL) 494e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 495e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 496e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (perf_session__create_kernel_maps(session) < 0) 497e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_delete; 498e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 499e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!perf_session__has_traces(session, "kmem record")) 500e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_delete; 501e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 502e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng setup_pager(); 503e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = perf_session__process_events(session, &event_ops); 504e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (err != 0) 505e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_delete; 506e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sort_result(); 507e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng print_result(session); 508e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_delete: 509e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_session__delete(session); 510e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return err; 511e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 512e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 513e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic const char * const kmem_usage[] = { 514e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "perf kmem [<options>] {record|stat}", 515e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng NULL 516e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 517e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 518e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r) 519e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 520e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (l->ptr < r->ptr) 521e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 522e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (l->ptr > r->ptr) 523e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 524e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 525e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 526e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 527e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct sort_dimension ptr_sort_dimension = { 528e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .name = "ptr", 529e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .cmp = ptr_cmp, 530e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 531e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 532e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int callsite_cmp(struct alloc_stat *l, struct alloc_stat *r) 533e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 534e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (l->call_site < r->call_site) 535e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 536e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (l->call_site > r->call_site) 537e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 538e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 539e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 540e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 541e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct sort_dimension callsite_sort_dimension = { 542e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .name = "callsite", 543e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .cmp = callsite_cmp, 544e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 545e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 546e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int hit_cmp(struct alloc_stat *l, struct alloc_stat *r) 547e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 548e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (l->hit < r->hit) 549e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 550e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (l->hit > r->hit) 551e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 552e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 553e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 554e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 555e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct sort_dimension hit_sort_dimension = { 556e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .name = "hit", 557e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .cmp = hit_cmp, 558e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 559e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 560e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int bytes_cmp(struct alloc_stat *l, struct alloc_stat *r) 561e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 562e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (l->bytes_alloc < r->bytes_alloc) 563e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 564e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (l->bytes_alloc > r->bytes_alloc) 565e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 566e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 567e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 568e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 569e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct sort_dimension bytes_sort_dimension = { 570e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .name = "bytes", 571e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .cmp = bytes_cmp, 572e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 573e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 574e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int frag_cmp(struct alloc_stat *l, struct alloc_stat *r) 575e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 576e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng double x, y; 577e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 578e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng x = fragmentation(l->bytes_req, l->bytes_alloc); 579e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng y = fragmentation(r->bytes_req, r->bytes_alloc); 580e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 581e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (x < y) 582e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 583e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (x > y) 584e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 585e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 586e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 587e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 588e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct sort_dimension frag_sort_dimension = { 589e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .name = "frag", 590e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .cmp = frag_cmp, 591e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 592e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 593e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int pingpong_cmp(struct alloc_stat *l, struct alloc_stat *r) 594e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 595e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (l->pingpong < r->pingpong) 596e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 597e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (l->pingpong > r->pingpong) 598e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 599e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 600e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 601e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 602e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct sort_dimension pingpong_sort_dimension = { 603e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .name = "pingpong", 604e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .cmp = pingpong_cmp, 605e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 606e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 607e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct sort_dimension *avail_sorts[] = { 608e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &ptr_sort_dimension, 609e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &callsite_sort_dimension, 610e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &hit_sort_dimension, 611e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &bytes_sort_dimension, 612e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &frag_sort_dimension, 613e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &pingpong_sort_dimension, 614e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 615e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 616e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define NUM_AVAIL_SORTS \ 617e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (int)(sizeof(avail_sorts) / sizeof(struct sort_dimension *)) 618e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 619e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int sort_dimension__add(const char *tok, struct list_head *list) 620e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 621e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct sort_dimension *sort; 622e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i; 623e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 624e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < NUM_AVAIL_SORTS; i++) { 625e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!strcmp(avail_sorts[i]->name, tok)) { 626e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sort = malloc(sizeof(*sort)); 627e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!sort) 628e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng die("malloc"); 629e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memcpy(sort, avail_sorts[i], sizeof(*sort)); 630e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_add_tail(&sort->list, list); 631e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 632e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 633e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 634e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 635e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 636e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 637e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 638e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int setup_sorting(struct list_head *sort_list, const char *arg) 639e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 640e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *tok; 641e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *str = strdup(arg); 642e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 643e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!str) 644e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng die("strdup"); 645e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 646e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (true) { 647e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tok = strsep(&str, ","); 648e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!tok) 649e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 650e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (sort_dimension__add(tok, sort_list) < 0) { 651e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng error("Unknown --sort key: '%s'", tok); 652e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 653e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 654e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 655e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 656e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(str); 657e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 658e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 659e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 660e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_sort_opt(const struct option *opt __used, 661e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *arg, int unset __used) 662e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 663e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!arg) 664e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 665e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 666e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (caller_flag > alloc_flag) 667e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return setup_sorting(&caller_sort, arg); 668e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 669e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return setup_sorting(&alloc_sort, arg); 670e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 671e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 672e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 673e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 674e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_caller_opt(const struct option *opt __used, 675e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *arg __used, int unset __used) 676e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 677e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng caller_flag = (alloc_flag + 1); 678e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 679e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 680e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 681e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_alloc_opt(const struct option *opt __used, 682e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *arg __used, int unset __used) 683e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 684e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng alloc_flag = (caller_flag + 1); 685e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 686e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 687e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 688e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_line_opt(const struct option *opt __used, 689e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *arg, int unset __used) 690e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 691e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int lines; 692e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 693e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!arg) 694e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 695e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 696e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lines = strtoul(arg, NULL, 10); 697e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 698e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (caller_flag > alloc_flag) 699e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng caller_lines = lines; 700e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 701e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng alloc_lines = lines; 702e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 703e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 704e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 705e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 706e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic const struct option kmem_options[] = { 707e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng OPT_STRING('i', "input", &input_name, "file", 708e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "input file name"), 709e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL, 710e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "show per-callsite statistics", 711e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parse_caller_opt), 712e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL, 713e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "show per-allocation statistics", 714e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parse_alloc_opt), 715e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng OPT_CALLBACK('s', "sort", NULL, "key[,key2...]", 716e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "sort by keys: ptr, call_site, bytes, hit, pingpong, frag", 717e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parse_sort_opt), 718e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng OPT_CALLBACK('l', "line", NULL, "num", 719e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "show n lines", 720e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parse_line_opt), 721e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), 722e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng OPT_END() 723e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 724e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 725e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic const char *record_args[] = { 726e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "record", 727e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "-a", 728e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "-R", 729e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "-f", 730e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "-c", "1", 731e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "-e", "kmem:kmalloc", 732e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "-e", "kmem:kmalloc_node", 733e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "-e", "kmem:kfree", 734e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "-e", "kmem:kmem_cache_alloc", 735e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "-e", "kmem:kmem_cache_alloc_node", 736e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "-e", "kmem:kmem_cache_free", 737e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 738e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 739e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __cmd_record(int argc, const char **argv) 740e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 741e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int rec_argc, i, j; 742e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char **rec_argv; 743e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 744e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rec_argc = ARRAY_SIZE(record_args) + argc - 1; 745e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rec_argv = calloc(rec_argc + 1, sizeof(char *)); 746e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 747e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (rec_argv == NULL) 748e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 749e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 750e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < ARRAY_SIZE(record_args); i++) 751e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rec_argv[i] = strdup(record_args[i]); 752e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 753e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (j = 1; j < (unsigned int)argc; j++, i++) 754e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rec_argv[i] = argv[j]; 755e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 756e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return cmd_record(i, rec_argv, NULL); 757e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 758e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 759e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint cmd_kmem(int argc, const char **argv, const char *prefix __used) 760e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 761e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng argc = parse_options(argc, argv, kmem_options, kmem_usage, 0); 762e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 763e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!argc) 764e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng usage_with_options(kmem_usage, kmem_options); 765e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 766e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol__init(); 767e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 768e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!strncmp(argv[0], "rec", 3)) { 769e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return __cmd_record(argc, argv); 770e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (!strcmp(argv[0], "stat")) { 771e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng setup_cpunode_map(); 772e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 773e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (list_empty(&caller_sort)) 774e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng setup_sorting(&caller_sort, default_sort_order); 775e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (list_empty(&alloc_sort)) 776e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng setup_sorting(&alloc_sort, default_sort_order); 777e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 778e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return __cmd_kmem(); 779e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else 780e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng usage_with_options(kmem_usage, kmem_options); 781e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 782e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 783e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 784