diff options
author | Andi Kleen <ak@linux.intel.com> | 2017-06-02 11:48:10 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-06-19 14:14:58 -0400 |
commit | 36ce565114b4e7e3b83f40309675f6b1720957e4 (patch) | |
tree | 9434b52227d5d22928bd64b295cc61ace5b1beba /tools/perf/builtin-script.c | |
parent | 8c1cedb4466809f9d741a4088314783cb88680a9 (diff) |
perf script: Allow adding and removing fields
With 'perf script' it is common that we just want to add or remove a field.
Currently this requires figuring out the long list of default fields and
specifying them first, and then adding/removing the new field.
This patch adds a new + - syntax to merely add or remove fields,
that allows more succint and clearer command lines
For example to remove the comm field from PMU samples:
Previously
$ perf script -F tid,cpu,time,event,sym,ip,dso,period | head -1
swapper 0 [000] 504345.383126: 1 cycles: ffffffff90060c66 native_write_msr ([kernel.kallsyms])
with the new syntax
perf script -F -comm | head -1
0 [000] 504345.383126: 1 cycles: ffffffff90060c66 native_write_msr ([kernel.kallsyms])
The new syntax cannot be mixed with normal overriding.
v2: Fix example in description. Use tid vs pid. No functional changes.
v3: Don't skip initialization when user specified explicit type.
v4: Rebase. Remove empty line.
Committer testing:
# perf record -a usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 1.748 MB perf.data (14 samples) ]
Without a explicit field list specified via -F, defaults to:
# perf script | head -2
perf 6338 [000] 18467.058607: 1 cycles: ffffffff89060c36 native_write_msr (/lib/modules/4.11.0-rc8+/build/vmlinux)
swapper 0 [001] 18467.058617: 1 cycles: ffffffff89060c36 native_write_msr (/lib/modules/4.11.0-rc8+/build/vmlinux)
#
Which is equivalent to:
# perf script -F comm,tid,cpu,time,period,event,ip,sym,dso | head -2
perf 6338 [000] 18467.058607: 1 cycles: ffffffff89060c36 native_write_msr (/lib/modules/4.11.0-rc8+/build/vmlinux)
swapper 0 [001] 18467.058617: 1 cycles: ffffffff89060c36 native_write_msr (/lib/modules/4.11.0-rc8+/build/vmlinux)
#
So if we want to remove the comm, as in your original example, we would have to
figure out the default field list and remove ' comm' from it:
# perf script -F tid,cpu,time,period,event,ip,sym,dso | head -2
6338 [000] 18467.058607: 1 cycles: ffffffff89060c36 native_write_msr (/lib/modules/4.11.0-rc8+/build/vmlinux)
0 [001] 18467.058617: 1 cycles: ffffffff89060c36 native_write_msr (/lib/modules/4.11.0-rc8+/build/vmlinux)
#
With your patch this becomes simpler, one can remove fields by prefixing them
with '-':
# perf script -F -comm | head -2
6338 [000] 18467.058607: 1 cycles: ffffffff89060c36 native_write_msr (/lib/modules/4.11.0-rc8+/build/vmlinux)
0 [001] 18467.058617: 1 cycles: ffffffff89060c36 native_write_msr (/lib/modules/4.11.0-rc8+/build/vmlinux)
#
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Milian Wolff <milian.wolff@kdab.com>
Link: http://lkml.kernel.org/r/20170602154810.15875-1-andi@firstfloor.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r-- | tools/perf/builtin-script.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 4761b0d7fcb5..afa84debc5c4 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -1727,6 +1727,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused, | |||
1727 | int rc = 0; | 1727 | int rc = 0; |
1728 | char *str = strdup(arg); | 1728 | char *str = strdup(arg); |
1729 | int type = -1; | 1729 | int type = -1; |
1730 | enum { DEFAULT, SET, ADD, REMOVE } change = DEFAULT; | ||
1730 | 1731 | ||
1731 | if (!str) | 1732 | if (!str) |
1732 | return -ENOMEM; | 1733 | return -ENOMEM; |
@@ -1772,6 +1773,10 @@ static int parse_output_fields(const struct option *opt __maybe_unused, | |||
1772 | goto out; | 1773 | goto out; |
1773 | } | 1774 | } |
1774 | 1775 | ||
1776 | /* Don't override defaults for +- */ | ||
1777 | if (strchr(str, '+') || strchr(str, '-')) | ||
1778 | goto parse; | ||
1779 | |||
1775 | if (output_set_by_user()) | 1780 | if (output_set_by_user()) |
1776 | pr_warning("Overriding previous field request for all events.\n"); | 1781 | pr_warning("Overriding previous field request for all events.\n"); |
1777 | 1782 | ||
@@ -1782,13 +1787,30 @@ static int parse_output_fields(const struct option *opt __maybe_unused, | |||
1782 | } | 1787 | } |
1783 | } | 1788 | } |
1784 | 1789 | ||
1790 | parse: | ||
1785 | for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) { | 1791 | for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) { |
1792 | if (*tok == '+') { | ||
1793 | if (change == SET) | ||
1794 | goto out_badmix; | ||
1795 | change = ADD; | ||
1796 | tok++; | ||
1797 | } else if (*tok == '-') { | ||
1798 | if (change == SET) | ||
1799 | goto out_badmix; | ||
1800 | change = REMOVE; | ||
1801 | tok++; | ||
1802 | } else { | ||
1803 | if (change != SET && change != DEFAULT) | ||
1804 | goto out_badmix; | ||
1805 | change = SET; | ||
1806 | } | ||
1807 | |||
1786 | for (i = 0; i < imax; ++i) { | 1808 | for (i = 0; i < imax; ++i) { |
1787 | if (strcmp(tok, all_output_options[i].str) == 0) | 1809 | if (strcmp(tok, all_output_options[i].str) == 0) |
1788 | break; | 1810 | break; |
1789 | } | 1811 | } |
1790 | if (i == imax && strcmp(tok, "flags") == 0) { | 1812 | if (i == imax && strcmp(tok, "flags") == 0) { |
1791 | print_flags = true; | 1813 | print_flags = change == REMOVE ? false : true; |
1792 | continue; | 1814 | continue; |
1793 | } | 1815 | } |
1794 | if (i == imax) { | 1816 | if (i == imax) { |
@@ -1805,8 +1827,12 @@ static int parse_output_fields(const struct option *opt __maybe_unused, | |||
1805 | if (output[j].invalid_fields & all_output_options[i].field) { | 1827 | if (output[j].invalid_fields & all_output_options[i].field) { |
1806 | pr_warning("\'%s\' not valid for %s events. Ignoring.\n", | 1828 | pr_warning("\'%s\' not valid for %s events. Ignoring.\n", |
1807 | all_output_options[i].str, event_type(j)); | 1829 | all_output_options[i].str, event_type(j)); |
1808 | } else | 1830 | } else { |
1809 | output[j].fields |= all_output_options[i].field; | 1831 | if (change == REMOVE) |
1832 | output[j].fields &= ~all_output_options[i].field; | ||
1833 | else | ||
1834 | output[j].fields |= all_output_options[i].field; | ||
1835 | } | ||
1810 | } | 1836 | } |
1811 | } else { | 1837 | } else { |
1812 | if (output[type].invalid_fields & all_output_options[i].field) { | 1838 | if (output[type].invalid_fields & all_output_options[i].field) { |
@@ -1826,7 +1852,11 @@ static int parse_output_fields(const struct option *opt __maybe_unused, | |||
1826 | "Events will not be displayed.\n", event_type(type)); | 1852 | "Events will not be displayed.\n", event_type(type)); |
1827 | } | 1853 | } |
1828 | } | 1854 | } |
1855 | goto out; | ||
1829 | 1856 | ||
1857 | out_badmix: | ||
1858 | fprintf(stderr, "Cannot mix +-field with overridden fields\n"); | ||
1859 | rc = -EINVAL; | ||
1830 | out: | 1860 | out: |
1831 | free(str); | 1861 | free(str); |
1832 | return rc; | 1862 | return rc; |
@@ -2444,6 +2474,7 @@ int cmd_script(int argc, const char **argv) | |||
2444 | symbol__config_symfs), | 2474 | symbol__config_symfs), |
2445 | OPT_CALLBACK('F', "fields", NULL, "str", | 2475 | OPT_CALLBACK('F', "fields", NULL, "str", |
2446 | "comma separated output fields prepend with 'type:'. " | 2476 | "comma separated output fields prepend with 'type:'. " |
2477 | "+field to add and -field to remove." | ||
2447 | "Valid types: hw,sw,trace,raw. " | 2478 | "Valid types: hw,sw,trace,raw. " |
2448 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," | 2479 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," |
2449 | "addr,symoff,period,iregs,brstack,brstacksym,flags," | 2480 | "addr,symoff,period,iregs,brstack,brstacksym,flags," |