diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-09-24 09:46:54 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-09-24 09:52:03 -0400 |
| commit | 0f7d2f1b65e3415854bbe842705f698a3350d7da (patch) | |
| tree | c8fc00abf4c00460d4c4c29259e1555c8d5de352 /tools/perf | |
| parent | 14907e73830a256ad726a35a93789a9bc9595490 (diff) | |
perf kmem: Use perf_evsel__intval and perf_session__set_tracepoints_handlers
Following the model of 'perf sched':
. raw_field_value searches first on the common fields, that are unused
in this tool
. Using perf_session__set_tracepoints_handlers will save all those
strcmp to find the right handler at sample processing time, do it just
once and get the handler from evsel->handler.func.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-v9x3q9rv4caxtox7wtjpchq5@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/builtin-kmem.c | 90 |
1 files changed, 45 insertions, 45 deletions
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index f5f8a6b745a..bc912c68f49 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include "builtin.h" | 1 | #include "builtin.h" |
| 2 | #include "perf.h" | 2 | #include "perf.h" |
| 3 | 3 | ||
| 4 | #include "util/evlist.h" | ||
| 4 | #include "util/evsel.h" | 5 | #include "util/evsel.h" |
| 5 | #include "util/util.h" | 6 | #include "util/util.h" |
| 6 | #include "util/cache.h" | 7 | #include "util/cache.h" |
| @@ -212,36 +213,38 @@ static int insert_caller_stat(unsigned long call_site, | |||
| 212 | } | 213 | } |
| 213 | 214 | ||
| 214 | static int perf_evsel__process_alloc_event(struct perf_evsel *evsel, | 215 | static int perf_evsel__process_alloc_event(struct perf_evsel *evsel, |
| 215 | struct perf_sample *sample, int node) | 216 | struct perf_sample *sample) |
| 216 | { | 217 | { |
| 217 | struct event_format *event = evsel->tp_format; | 218 | unsigned long ptr = perf_evsel__intval(evsel, sample, "ptr"), |
| 218 | void *data = sample->raw_data; | 219 | call_site = perf_evsel__intval(evsel, sample, "call_site"); |
| 219 | unsigned long call_site; | 220 | int bytes_req = perf_evsel__intval(evsel, sample, "bytes_req"), |
| 220 | unsigned long ptr; | 221 | bytes_alloc = perf_evsel__intval(evsel, sample, "bytes_alloc"); |
| 221 | int bytes_req, cpu = sample->cpu; | 222 | |
| 222 | int bytes_alloc; | 223 | if (insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, sample->cpu) || |
| 223 | int node1, node2; | ||
| 224 | |||
| 225 | ptr = raw_field_value(event, "ptr", data); | ||
| 226 | call_site = raw_field_value(event, "call_site", data); | ||
| 227 | bytes_req = raw_field_value(event, "bytes_req", data); | ||
| 228 | bytes_alloc = raw_field_value(event, "bytes_alloc", data); | ||
| 229 | |||
| 230 | if (insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, cpu) || | ||
| 231 | insert_caller_stat(call_site, bytes_req, bytes_alloc)) | 224 | insert_caller_stat(call_site, bytes_req, bytes_alloc)) |
| 232 | return -1; | 225 | return -1; |
| 233 | 226 | ||
| 234 | total_requested += bytes_req; | 227 | total_requested += bytes_req; |
| 235 | total_allocated += bytes_alloc; | 228 | total_allocated += bytes_alloc; |
| 236 | 229 | ||
| 237 | if (node) { | 230 | nr_allocs++; |
| 238 | node1 = cpunode_map[cpu]; | 231 | return 0; |
| 239 | node2 = raw_field_value(event, "node", data); | 232 | } |
| 233 | |||
| 234 | static int perf_evsel__process_alloc_node_event(struct perf_evsel *evsel, | ||
| 235 | struct perf_sample *sample) | ||
| 236 | { | ||
| 237 | int ret = perf_evsel__process_alloc_event(evsel, sample); | ||
| 238 | |||
| 239 | if (!ret) { | ||
| 240 | int node1 = cpunode_map[sample->cpu], | ||
| 241 | node2 = perf_evsel__intval(evsel, sample, "node"); | ||
| 242 | |||
| 240 | if (node1 != node2) | 243 | if (node1 != node2) |
| 241 | nr_cross_allocs++; | 244 | nr_cross_allocs++; |
| 242 | } | 245 | } |
| 243 | nr_allocs++; | 246 | |
| 244 | return 0; | 247 | return ret; |
| 245 | } | 248 | } |
| 246 | 249 | ||
| 247 | static int ptr_cmp(struct alloc_stat *, struct alloc_stat *); | 250 | static int ptr_cmp(struct alloc_stat *, struct alloc_stat *); |
| @@ -275,8 +278,7 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr, | |||
| 275 | static int perf_evsel__process_free_event(struct perf_evsel *evsel, | 278 | static int perf_evsel__process_free_event(struct perf_evsel *evsel, |
| 276 | struct perf_sample *sample) | 279 | struct perf_sample *sample) |
| 277 | { | 280 | { |
| 278 | unsigned long ptr = raw_field_value(evsel->tp_format, "ptr", | 281 | unsigned long ptr = perf_evsel__intval(evsel, sample, "ptr"); |
| 279 | sample->raw_data); | ||
| 280 | struct alloc_stat *s_alloc, *s_caller; | 282 | struct alloc_stat *s_alloc, *s_caller; |
| 281 | 283 | ||
| 282 | s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp); | 284 | s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp); |
| @@ -297,28 +299,8 @@ static int perf_evsel__process_free_event(struct perf_evsel *evsel, | |||
| 297 | return 0; | 299 | return 0; |
| 298 | } | 300 | } |
| 299 | 301 | ||
| 300 | static int perf_evsel__process_kmem_event(struct perf_evsel *evsel, | 302 | typedef int (*tracepoint_handler)(struct perf_evsel *evsel, |
| 301 | struct perf_sample *sample) | 303 | struct perf_sample *sample); |
| 302 | { | ||
| 303 | struct event_format *event = evsel->tp_format; | ||
| 304 | |||
| 305 | if (!strcmp(event->name, "kmalloc") || | ||
| 306 | !strcmp(event->name, "kmem_cache_alloc")) { | ||
| 307 | return perf_evsel__process_alloc_event(evsel, sample, 0); | ||
| 308 | } | ||
| 309 | |||
| 310 | if (!strcmp(event->name, "kmalloc_node") || | ||
| 311 | !strcmp(event->name, "kmem_cache_alloc_node")) { | ||
| 312 | return perf_evsel__process_alloc_event(evsel, sample, 1); | ||
| 313 | } | ||
| 314 | |||
| 315 | if (!strcmp(event->name, "kfree") || | ||
| 316 | !strcmp(event->name, "kmem_cache_free")) { | ||
| 317 | return perf_evsel__process_free_event(evsel, sample); | ||
| 318 | } | ||
| 319 | |||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | 304 | ||
| 323 | static int process_sample_event(struct perf_tool *tool __maybe_unused, | 305 | static int process_sample_event(struct perf_tool *tool __maybe_unused, |
| 324 | union perf_event *event, | 306 | union perf_event *event, |
| @@ -336,7 +318,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, | |||
| 336 | 318 | ||
| 337 | dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); | 319 | dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); |
| 338 | 320 | ||
| 339 | return perf_evsel__process_kmem_event(evsel, sample); | 321 | if (evsel->handler.func != NULL) { |
| 322 | tracepoint_handler f = evsel->handler.func; | ||
| 323 | return f(evsel, sample); | ||
| 324 | } | ||
| 325 | |||
| 326 | return 0; | ||
| 340 | } | 327 | } |
| 341 | 328 | ||
| 342 | static struct perf_tool perf_kmem = { | 329 | static struct perf_tool perf_kmem = { |
| @@ -498,6 +485,14 @@ static int __cmd_kmem(void) | |||
| 498 | { | 485 | { |
| 499 | int err = -EINVAL; | 486 | int err = -EINVAL; |
| 500 | struct perf_session *session; | 487 | struct perf_session *session; |
| 488 | const struct perf_evsel_str_handler kmem_tracepoints[] = { | ||
| 489 | { "kmem:kmalloc", perf_evsel__process_alloc_event, }, | ||
| 490 | { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, | ||
| 491 | { "kmem:kmalloc_node", perf_evsel__process_alloc_node_event, }, | ||
| 492 | { "kmem:kmem_cache_alloc_node", perf_evsel__process_alloc_node_event, }, | ||
| 493 | { "kmem:kfree", perf_evsel__process_free_event, }, | ||
| 494 | { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, | ||
| 495 | }; | ||
| 501 | 496 | ||
| 502 | session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_kmem); | 497 | session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_kmem); |
| 503 | if (session == NULL) | 498 | if (session == NULL) |
| @@ -509,6 +504,11 @@ static int __cmd_kmem(void) | |||
| 509 | if (!perf_session__has_traces(session, "kmem record")) | 504 | if (!perf_session__has_traces(session, "kmem record")) |
| 510 | goto out_delete; | 505 | goto out_delete; |
| 511 | 506 | ||
| 507 | if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) { | ||
| 508 | pr_err("Initializing perf session tracepoint handlers failed\n"); | ||
| 509 | return -1; | ||
| 510 | } | ||
| 511 | |||
| 512 | setup_pager(); | 512 | setup_pager(); |
| 513 | err = perf_session__process_events(session, &perf_kmem); | 513 | err = perf_session__process_events(session, &perf_kmem); |
| 514 | if (err != 0) | 514 | if (err != 0) |
