aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2017-06-02 11:48:10 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-06-19 14:14:58 -0400
commit36ce565114b4e7e3b83f40309675f6b1720957e4 (patch)
tree9434b52227d5d22928bd64b295cc61ace5b1beba /tools/perf/builtin-script.c
parent8c1cedb4466809f9d741a4088314783cb88680a9 (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.c37
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
1790parse:
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
1857out_badmix:
1858 fprintf(stderr, "Cannot mix +-field with overridden fields\n");
1859 rc = -EINVAL;
1830out: 1860out:
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,"