diff options
| author | Ingo Molnar <mingo@kernel.org> | 2016-01-09 11:17:33 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2016-01-09 11:17:33 -0500 |
| commit | 3eb9ede23bdd96e9ba60e2b4d4d17a7c35d58448 (patch) | |
| tree | 2bed2ab8e7fa6e6202154992433bb24ecdb9a24d /tools/perf/util/scripting-engines/trace-event-python.c | |
| parent | 9cc2617de5b9222abb39cd02e90d57dfea99c6d7 (diff) | |
| parent | 775d8a1b0d75211cc6123915c6b5b688f2002478 (diff) | |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
New features:
- Allow using trace events fields as sort order keys, making 'perf evlist --trace_fields'
show those, and then the user can select a subset and use like:
perf top -e sched:sched_switch -s prev_comm,next_comm
That works as well in 'perf report' when handling files containing
tracepoints.
The default when just tracepoint events are found in a perf.data file is to
format it like ftrace, using the libtraceevent formatters, plugins, etc (Namhyung Kim)
- Add support in 'perf script' to process 'perf stat record' generated files,
culminating in a python perf script that calculates CPI (Cycles per
Instruction) (Jiri Olsa)
- Show random perf tool tips in the 'perf report' bottom line (Namhyung Kim)
- perf report now defaults to --group if the perf.data file has grouped events, try it with:
# perf record -e '{cycles,instructions}' -a sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 1.093 MB perf.data (1247 samples) ]
# perf report
# Samples: 1K of event 'anon group { cycles, instructions }'
# Event count (approx.): 1955219195
#
# Overhead Command Shared Object Symbol
2.86% 0.22% swapper [kernel.kallsyms] [k] intel_idle
1.05% 0.33% firefox libxul.so [.] js::SetObjectElement
1.05% 0.00% kworker/0:3 [kernel.kallsyms] [k] gen6_ring_get_seqno
0.88% 0.17% chrome chrome [.] 0x0000000000ee27ab
0.65% 0.86% firefox libxul.so [.] js::ValueToId<(js::AllowGC)1>
0.64% 0.23% JS Helper libxul.so [.] js::SplayTree<js::jit::LiveRange*, js::jit::LiveRange>::splay
0.62% 1.27% firefox libxul.so [.] js::GetIterator
0.61% 1.74% firefox libxul.so [.] js::NativeSetProperty
0.61% 0.31% firefox libxul.so [.] js::SetPropertyByDefining
User visible fixes:
- Coect data mmaps so that the DWARF unwinder can handle usecases needing them,
like softice (Jiri Olsa)
- Decay callchains in fractal mode, fixing up cases where 'perf top -g' would
show entries with more than 100% (Namhyung Kim)
Infrastructure changes:
- Sync tools/lib with the lib/ in the kernel sources for find_bit.c and
move bitmap.[ch] from tools/perf/util/ to tools/lib/ (Arnaldo Carvalho de Melo)
- No need to set attr.sample_freq in some 'perf test' entries that only
want to deal with PERF_RECORD_ meta-events, improve a bit error output
for CQM test (Arnaldo Carvalho de Melo)
- Fix python binding build, adding some missing object files now required
due to cpumap using find_bit stuff (Arnaldo Carvalho de Melo)
- tools/build improvemnts (Jiri Olsa)
- Add more files to cscope/ctags databases (Jiri Olsa)
- Do not show 'trace' in 'perf help' if it is not compiled in (Jiri Olsa)
- Make perf_evlist__open() open evsels with their cpus and threads,
like perf record does, making them consistent (Adrian Hunter)
- Fix pmu snapshot initialization bug (Stephane Eranian)
- Add missing headers in perf's MANIFEST (Wang Nan)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
| -rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 115 |
1 files changed, 109 insertions, 6 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index a8e825fca42a..d72fafc1c800 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
| @@ -41,6 +41,9 @@ | |||
| 41 | #include "../thread-stack.h" | 41 | #include "../thread-stack.h" |
| 42 | #include "../trace-event.h" | 42 | #include "../trace-event.h" |
| 43 | #include "../machine.h" | 43 | #include "../machine.h" |
| 44 | #include "thread_map.h" | ||
| 45 | #include "cpumap.h" | ||
| 46 | #include "stat.h" | ||
| 44 | 47 | ||
| 45 | PyMODINIT_FUNC initperf_trace_context(void); | 48 | PyMODINIT_FUNC initperf_trace_context(void); |
| 46 | 49 | ||
| @@ -859,6 +862,104 @@ static void python_process_event(union perf_event *event, | |||
| 859 | } | 862 | } |
| 860 | } | 863 | } |
| 861 | 864 | ||
| 865 | static void get_handler_name(char *str, size_t size, | ||
| 866 | struct perf_evsel *evsel) | ||
| 867 | { | ||
| 868 | char *p = str; | ||
| 869 | |||
| 870 | scnprintf(str, size, "stat__%s", perf_evsel__name(evsel)); | ||
| 871 | |||
| 872 | while ((p = strchr(p, ':'))) { | ||
| 873 | *p = '_'; | ||
| 874 | p++; | ||
| 875 | } | ||
| 876 | } | ||
| 877 | |||
| 878 | static void | ||
| 879 | process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp, | ||
| 880 | struct perf_counts_values *count) | ||
| 881 | { | ||
| 882 | PyObject *handler, *t; | ||
| 883 | static char handler_name[256]; | ||
| 884 | int n = 0; | ||
| 885 | |||
| 886 | t = PyTuple_New(MAX_FIELDS); | ||
| 887 | if (!t) | ||
| 888 | Py_FatalError("couldn't create Python tuple"); | ||
| 889 | |||
| 890 | get_handler_name(handler_name, sizeof(handler_name), | ||
| 891 | counter); | ||
| 892 | |||
| 893 | handler = get_handler(handler_name); | ||
| 894 | if (!handler) { | ||
| 895 | pr_debug("can't find python handler %s\n", handler_name); | ||
| 896 | return; | ||
| 897 | } | ||
| 898 | |||
| 899 | PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); | ||
| 900 | PyTuple_SetItem(t, n++, PyInt_FromLong(thread)); | ||
| 901 | |||
| 902 | tuple_set_u64(t, n++, tstamp); | ||
| 903 | tuple_set_u64(t, n++, count->val); | ||
| 904 | tuple_set_u64(t, n++, count->ena); | ||
| 905 | tuple_set_u64(t, n++, count->run); | ||
| 906 | |||
| 907 | if (_PyTuple_Resize(&t, n) == -1) | ||
| 908 | Py_FatalError("error resizing Python tuple"); | ||
| 909 | |||
| 910 | call_object(handler, t, handler_name); | ||
| 911 | |||
| 912 | Py_DECREF(t); | ||
| 913 | } | ||
| 914 | |||
| 915 | static void python_process_stat(struct perf_stat_config *config, | ||
| 916 | struct perf_evsel *counter, u64 tstamp) | ||
| 917 | { | ||
| 918 | struct thread_map *threads = counter->threads; | ||
| 919 | struct cpu_map *cpus = counter->cpus; | ||
| 920 | int cpu, thread; | ||
| 921 | |||
| 922 | if (config->aggr_mode == AGGR_GLOBAL) { | ||
| 923 | process_stat(counter, -1, -1, tstamp, | ||
| 924 | &counter->counts->aggr); | ||
| 925 | return; | ||
| 926 | } | ||
| 927 | |||
| 928 | for (thread = 0; thread < threads->nr; thread++) { | ||
| 929 | for (cpu = 0; cpu < cpus->nr; cpu++) { | ||
| 930 | process_stat(counter, cpus->map[cpu], | ||
| 931 | thread_map__pid(threads, thread), tstamp, | ||
| 932 | perf_counts(counter->counts, cpu, thread)); | ||
| 933 | } | ||
| 934 | } | ||
| 935 | } | ||
| 936 | |||
| 937 | static void python_process_stat_interval(u64 tstamp) | ||
| 938 | { | ||
| 939 | PyObject *handler, *t; | ||
| 940 | static const char handler_name[] = "stat__interval"; | ||
| 941 | int n = 0; | ||
| 942 | |||
| 943 | t = PyTuple_New(MAX_FIELDS); | ||
| 944 | if (!t) | ||
| 945 | Py_FatalError("couldn't create Python tuple"); | ||
| 946 | |||
| 947 | handler = get_handler(handler_name); | ||
| 948 | if (!handler) { | ||
| 949 | pr_debug("can't find python handler %s\n", handler_name); | ||
| 950 | return; | ||
| 951 | } | ||
| 952 | |||
| 953 | tuple_set_u64(t, n++, tstamp); | ||
| 954 | |||
| 955 | if (_PyTuple_Resize(&t, n) == -1) | ||
| 956 | Py_FatalError("error resizing Python tuple"); | ||
| 957 | |||
| 958 | call_object(handler, t, handler_name); | ||
| 959 | |||
| 960 | Py_DECREF(t); | ||
| 961 | } | ||
| 962 | |||
| 862 | static int run_start_sub(void) | 963 | static int run_start_sub(void) |
| 863 | { | 964 | { |
| 864 | main_module = PyImport_AddModule("__main__"); | 965 | main_module = PyImport_AddModule("__main__"); |
| @@ -1201,10 +1302,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
| 1201 | } | 1302 | } |
| 1202 | 1303 | ||
| 1203 | struct scripting_ops python_scripting_ops = { | 1304 | struct scripting_ops python_scripting_ops = { |
| 1204 | .name = "Python", | 1305 | .name = "Python", |
| 1205 | .start_script = python_start_script, | 1306 | .start_script = python_start_script, |
| 1206 | .flush_script = python_flush_script, | 1307 | .flush_script = python_flush_script, |
| 1207 | .stop_script = python_stop_script, | 1308 | .stop_script = python_stop_script, |
| 1208 | .process_event = python_process_event, | 1309 | .process_event = python_process_event, |
| 1209 | .generate_script = python_generate_script, | 1310 | .process_stat = python_process_stat, |
| 1311 | .process_stat_interval = python_process_stat_interval, | ||
| 1312 | .generate_script = python_generate_script, | ||
| 1210 | }; | 1313 | }; |
