aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-sched.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-11-28 14:57:40 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-11-28 14:57:40 -0500
commitee29be625bd7b115d45eba4b0526ff3e24bf3ca0 (patch)
tree1ef1189e0fe02511642e5f74f463d888dfa34bec /tools/perf/builtin-sched.c
parente7984b7bee2fca8f582f5bc2bf1e6c93420a5dd5 (diff)
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the associated evsel, add handler func + data to struct perf_evsel to avoid using chains of if(strcmp(event_name)) and also to avoid all the linear list searches via trace_event_find. To demonstrate the technique convert 'perf sched' to it: # perf sched record sleep 5m And then: Performance counter stats for '/tmp/oldperf sched lat': 646.929438 task-clock # 0.999 CPUs utilized 9 context-switches # 0.000 M/sec 0 CPU-migrations # 0.000 M/sec 20,901 page-faults # 0.032 M/sec 1,290,144,450 cycles # 1.994 GHz <not supported> stalled-cycles-frontend <not supported> stalled-cycles-backend 1,606,158,439 instructions # 1.24 insns per cycle 339,088,395 branches # 524.151 M/sec 4,550,735 branch-misses # 1.34% of all branches 0.647524759 seconds time elapsed Versus: Performance counter stats for 'perf sched lat': 473.564691 task-clock # 0.999 CPUs utilized 9 context-switches # 0.000 M/sec 0 CPU-migrations # 0.000 M/sec 20,903 page-faults # 0.044 M/sec 944,367,984 cycles # 1.994 GHz <not supported> stalled-cycles-frontend <not supported> stalled-cycles-backend 1,442,385,571 instructions # 1.53 insns per cycle 308,383,106 branches # 651.195 M/sec 4,481,784 branch-misses # 1.45% of all branches 0.474215751 seconds time elapsed [root@emilia ~]# Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> 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-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-sched.c')
-rw-r--r--tools/perf/builtin-sched.c149
1 files changed, 74 insertions, 75 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 0ee868e6f63b..6284ed2317f2 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -2,6 +2,7 @@
2#include "perf.h" 2#include "perf.h"
3 3
4#include "util/util.h" 4#include "util/util.h"
5#include "util/evlist.h"
5#include "util/cache.h" 6#include "util/cache.h"
6#include "util/evsel.h" 7#include "util/evsel.h"
7#include "util/symbol.h" 8#include "util/symbol.h"
@@ -1358,12 +1359,13 @@ static void sort_lat(void)
1358static struct trace_sched_handler *trace_handler; 1359static struct trace_sched_handler *trace_handler;
1359 1360
1360static void 1361static void
1361process_sched_wakeup_event(void *data, struct machine *machine, 1362process_sched_wakeup_event(struct perf_tool *tool __used,
1362 struct event *event, 1363 struct event *event,
1363 int cpu __used, 1364 struct perf_sample *sample,
1364 u64 timestamp __used, 1365 struct machine *machine,
1365 struct thread *thread __used) 1366 struct thread *thread)
1366{ 1367{
1368 void *data = sample->raw_data;
1367 struct trace_wakeup_event wakeup_event; 1369 struct trace_wakeup_event wakeup_event;
1368 1370
1369 FILL_COMMON_FIELDS(wakeup_event, event, data); 1371 FILL_COMMON_FIELDS(wakeup_event, event, data);
@@ -1376,7 +1378,7 @@ process_sched_wakeup_event(void *data, struct machine *machine,
1376 1378
1377 if (trace_handler->wakeup_event) 1379 if (trace_handler->wakeup_event)
1378 trace_handler->wakeup_event(&wakeup_event, machine, event, 1380 trace_handler->wakeup_event(&wakeup_event, machine, event,
1379 cpu, timestamp, thread); 1381 sample->cpu, sample->time, thread);
1380} 1382}
1381 1383
1382/* 1384/*
@@ -1471,14 +1473,15 @@ map_switch_event(struct trace_switch_event *switch_event,
1471 } 1473 }
1472} 1474}
1473 1475
1474
1475static void 1476static void
1476process_sched_switch_event(void *data, struct machine *machine, 1477process_sched_switch_event(struct perf_tool *tool __used,
1477 struct event *event, 1478 struct event *event,
1478 int this_cpu, 1479 struct perf_sample *sample,
1479 u64 timestamp __used, 1480 struct machine *machine,
1480 struct thread *thread __used) 1481 struct thread *thread)
1481{ 1482{
1483 int this_cpu = sample->cpu;
1484 void *data = sample->raw_data;
1482 struct trace_switch_event switch_event; 1485 struct trace_switch_event switch_event;
1483 1486
1484 FILL_COMMON_FIELDS(switch_event, event, data); 1487 FILL_COMMON_FIELDS(switch_event, event, data);
@@ -1501,18 +1504,19 @@ process_sched_switch_event(void *data, struct machine *machine,
1501 } 1504 }
1502 if (trace_handler->switch_event) 1505 if (trace_handler->switch_event)
1503 trace_handler->switch_event(&switch_event, machine, event, 1506 trace_handler->switch_event(&switch_event, machine, event,
1504 this_cpu, timestamp, thread); 1507 this_cpu, sample->time, thread);
1505 1508
1506 curr_pid[this_cpu] = switch_event.next_pid; 1509 curr_pid[this_cpu] = switch_event.next_pid;
1507} 1510}
1508 1511
1509static void 1512static void
1510process_sched_runtime_event(void *data, struct machine *machine, 1513process_sched_runtime_event(struct perf_tool *tool __used,
1511 struct event *event, 1514 struct event *event,
1512 int cpu __used, 1515 struct perf_sample *sample,
1513 u64 timestamp __used, 1516 struct machine *machine,
1514 struct thread *thread __used) 1517 struct thread *thread)
1515{ 1518{
1519 void *data = sample->raw_data;
1516 struct trace_runtime_event runtime_event; 1520 struct trace_runtime_event runtime_event;
1517 1521
1518 FILL_ARRAY(runtime_event, comm, event, data); 1522 FILL_ARRAY(runtime_event, comm, event, data);
@@ -1521,16 +1525,18 @@ process_sched_runtime_event(void *data, struct machine *machine,
1521 FILL_FIELD(runtime_event, vruntime, event, data); 1525 FILL_FIELD(runtime_event, vruntime, event, data);
1522 1526
1523 if (trace_handler->runtime_event) 1527 if (trace_handler->runtime_event)
1524 trace_handler->runtime_event(&runtime_event, machine, event, cpu, timestamp, thread); 1528 trace_handler->runtime_event(&runtime_event, machine, event,
1529 sample->cpu, sample->time, thread);
1525} 1530}
1526 1531
1527static void 1532static void
1528process_sched_fork_event(void *data, 1533process_sched_fork_event(struct perf_tool *tool __used,
1529 struct event *event, 1534 struct event *event,
1530 int cpu __used, 1535 struct perf_sample *sample,
1531 u64 timestamp __used, 1536 struct machine *machine __used,
1532 struct thread *thread __used) 1537 struct thread *thread)
1533{ 1538{
1539 void *data = sample->raw_data;
1534 struct trace_fork_event fork_event; 1540 struct trace_fork_event fork_event;
1535 1541
1536 FILL_COMMON_FIELDS(fork_event, event, data); 1542 FILL_COMMON_FIELDS(fork_event, event, data);
@@ -1542,13 +1548,14 @@ process_sched_fork_event(void *data,
1542 1548
1543 if (trace_handler->fork_event) 1549 if (trace_handler->fork_event)
1544 trace_handler->fork_event(&fork_event, event, 1550 trace_handler->fork_event(&fork_event, event,
1545 cpu, timestamp, thread); 1551 sample->cpu, sample->time, thread);
1546} 1552}
1547 1553
1548static void 1554static void
1549process_sched_exit_event(struct event *event, 1555process_sched_exit_event(struct perf_tool *tool __used,
1550 int cpu __used, 1556 struct event *event,
1551 u64 timestamp __used, 1557 struct perf_sample *sample __used,
1558 struct machine *machine __used,
1552 struct thread *thread __used) 1559 struct thread *thread __used)
1553{ 1560{
1554 if (verbose) 1561 if (verbose)
@@ -1556,12 +1563,13 @@ process_sched_exit_event(struct event *event,
1556} 1563}
1557 1564
1558static void 1565static void
1559process_sched_migrate_task_event(void *data, struct machine *machine, 1566process_sched_migrate_task_event(struct perf_tool *tool __used,
1560 struct event *event, 1567 struct event *event,
1561 int cpu __used, 1568 struct perf_sample *sample,
1562 u64 timestamp __used, 1569 struct machine *machine,
1563 struct thread *thread __used) 1570 struct thread *thread)
1564{ 1571{
1572 void *data = sample->raw_data;
1565 struct trace_migrate_task_event migrate_task_event; 1573 struct trace_migrate_task_event migrate_task_event;
1566 1574
1567 FILL_COMMON_FIELDS(migrate_task_event, event, data); 1575 FILL_COMMON_FIELDS(migrate_task_event, event, data);
@@ -1573,67 +1581,46 @@ process_sched_migrate_task_event(void *data, struct machine *machine,
1573 1581
1574 if (trace_handler->migrate_task_event) 1582 if (trace_handler->migrate_task_event)
1575 trace_handler->migrate_task_event(&migrate_task_event, machine, 1583 trace_handler->migrate_task_event(&migrate_task_event, machine,
1576 event, cpu, timestamp, thread); 1584 event, sample->cpu,
1585 sample->time, thread);
1577} 1586}
1578 1587
1579static void process_raw_event(union perf_event *raw_event __used, 1588typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event *event,
1580 struct machine *machine, void *data, int cpu, 1589 struct perf_sample *sample,
1581 u64 timestamp, struct thread *thread) 1590 struct machine *machine,
1582{ 1591 struct thread *thread);
1583 struct event *event;
1584 int type;
1585
1586
1587 type = trace_parse_common_type(data);
1588 event = trace_find_event(type);
1589
1590 if (!strcmp(event->name, "sched_switch"))
1591 process_sched_switch_event(data, machine, event, cpu, timestamp, thread);
1592 if (!strcmp(event->name, "sched_stat_runtime"))
1593 process_sched_runtime_event(data, machine, event, cpu, timestamp, thread);
1594 if (!strcmp(event->name, "sched_wakeup"))
1595 process_sched_wakeup_event(data, machine, event, cpu, timestamp, thread);
1596 if (!strcmp(event->name, "sched_wakeup_new"))
1597 process_sched_wakeup_event(data, machine, event, cpu, timestamp, thread);
1598 if (!strcmp(event->name, "sched_process_fork"))
1599 process_sched_fork_event(data, event, cpu, timestamp, thread);
1600 if (!strcmp(event->name, "sched_process_exit"))
1601 process_sched_exit_event(event, cpu, timestamp, thread);
1602 if (!strcmp(event->name, "sched_migrate_task"))
1603 process_sched_migrate_task_event(data, machine, event, cpu, timestamp, thread);
1604}
1605 1592
1606static int process_sample_event(struct perf_tool *tool __used, 1593static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
1607 union perf_event *event, 1594 union perf_event *event __used,
1608 struct perf_sample *sample, 1595 struct perf_sample *sample,
1609 struct perf_evsel *evsel, 1596 struct perf_evsel *evsel,
1610 struct machine *machine) 1597 struct machine *machine)
1611{ 1598{
1612 struct thread *thread; 1599 struct thread *thread = machine__findnew_thread(machine, sample->pid);
1613
1614 if (!(evsel->attr.sample_type & PERF_SAMPLE_RAW))
1615 return 0;
1616 1600
1617 thread = machine__findnew_thread(machine, sample->pid);
1618 if (thread == NULL) { 1601 if (thread == NULL) {
1619 pr_debug("problem processing %d event, skipping it.\n", 1602 pr_debug("problem processing %s event, skipping it.\n",
1620 event->header.type); 1603 evsel->name);
1621 return -1; 1604 return -1;
1622 } 1605 }
1623 1606
1624 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1607 evsel->hists.stats.total_period += sample->period;
1608 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
1625 1609
1626 if (profile_cpu != -1 && profile_cpu != (int)sample->cpu) 1610 if (evsel->handler.func != NULL) {
1627 return 0; 1611 tracepoint_handler f = evsel->handler.func;
1628 1612
1629 process_raw_event(event, machine, sample->raw_data, sample->cpu, 1613 if (evsel->handler.data == NULL)
1630 sample->time, thread); 1614 evsel->handler.data = trace_find_event(evsel->attr.config);
1615
1616 f(tool, evsel->handler.data, sample, machine, thread);
1617 }
1631 1618
1632 return 0; 1619 return 0;
1633} 1620}
1634 1621
1635static struct perf_tool perf_sched = { 1622static struct perf_tool perf_sched = {
1636 .sample = process_sample_event, 1623 .sample = perf_sched__process_tracepoint_sample,
1637 .comm = perf_event__process_comm, 1624 .comm = perf_event__process_comm,
1638 .lost = perf_event__process_lost, 1625 .lost = perf_event__process_lost,
1639 .fork = perf_event__process_task, 1626 .fork = perf_event__process_task,
@@ -1643,11 +1630,23 @@ static struct perf_tool perf_sched = {
1643static void read_events(bool destroy, struct perf_session **psession) 1630static void read_events(bool destroy, struct perf_session **psession)
1644{ 1631{
1645 int err = -EINVAL; 1632 int err = -EINVAL;
1633 const struct perf_evsel_str_handler handlers[] = {
1634 { "sched:sched_switch", process_sched_switch_event, },
1635 { "sched:sched_stat_runtime", process_sched_runtime_event, },
1636 { "sched:sched_wakeup", process_sched_wakeup_event, },
1637 { "sched:sched_wakeup_new", process_sched_wakeup_event, },
1638 { "sched:sched_process_fork", process_sched_fork_event, },
1639 { "sched:sched_process_exit", process_sched_exit_event, },
1640 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1641 };
1646 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 1642 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1647 0, false, &perf_sched); 1643 0, false, &perf_sched);
1648 if (session == NULL) 1644 if (session == NULL)
1649 die("No Memory"); 1645 die("No Memory");
1650 1646
1647 err = perf_evlist__set_tracepoints_handlers_array(session->evlist, handlers);
1648 assert(err == 0);
1649
1651 if (perf_session__has_traces(session, "record -R")) { 1650 if (perf_session__has_traces(session, "record -R")) {
1652 err = perf_session__process_events(session, &perf_sched); 1651 err = perf_session__process_events(session, &perf_sched);
1653 if (err) 1652 if (err)