All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] perf tools: Add 'perf-config' command
@ 2015-04-12 14:44 Taeung Song
  2015-04-12 14:44 ` [PATCH 2/2] perf tools: Add a option 'remove' to perf-config and features which get or set a config variable Taeung Song
  2015-04-13  6:16 ` [PATCH 1/2] perf tools: Add 'perf-config' command Namhyung Kim
  0 siblings, 2 replies; 12+ messages in thread
From: Taeung Song @ 2015-04-12 14:44 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: linux-kernel, jolsa, namhyung, Taeung Song

The perf configuration file contains many variables which can make
the perf command's action more effective and more skilful.
But looking through state of configuration is difficult and
there's no knowing what kind of other variables except variables in perfconfig.example exist.
So This patch adds 'perf-config' command with '--all' option and a document for it.

Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
 tools/perf/Build                            |   1 +
 tools/perf/Documentation/perf-config.txt    | 433 ++++++++++++++++++++++++++++
 tools/perf/Documentation/perfconfig.example |  65 ++++-
 tools/perf/builtin-config.c                 |  71 +++++
 tools/perf/builtin.h                        |   1 +
 tools/perf/command-list.txt                 |   1 +
 tools/perf/perf.c                           |   1 +
 7 files changed, 562 insertions(+), 11 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-config.txt
 create mode 100644 tools/perf/builtin-config.c

diff --git a/tools/perf/Build b/tools/perf/Build
index b77370e..3c1f437 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -1,5 +1,6 @@
 perf-y += builtin-bench.o
 perf-y += builtin-annotate.o
+perf-y += builtin-config.o
 perf-y += builtin-diff.o
 perf-y += builtin-evlist.o
 perf-y += builtin-help.o
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
new file mode 100644
index 0000000..b251702
--- /dev/null
+++ b/tools/perf/Documentation/perf-config.txt
@@ -0,0 +1,433 @@
+perf-config(1)
+==============
+
+NAME
+----
+perf-config - Get and set variables in configuration file.
+
+SYNOPSIS
+--------
+[verse]
+'perf config' -a | --all
+
+DESCRIPTION
+-----------
+You can manage variables in configuration file with this command.
+
+OPTIONS
+-------
+
+-a::
+--all::
+	Show all variables with key and value into each sections.
+
+CONFIGURATION FILE
+------------------
+
+The Perf configuration file contain many variables which can make
+the perf command's action more effective, more skilful.
+The '$HOME/.perfconfig' file is used to store a per-user configuration.
+The file 'etc/perfconfig' or '$(sysconfdir)/perfconfig' can be used to
+store a system-wide default configuration.
+
+The variables are divided into sections. In each sections, the variables
+can contain a key and values.
+
+Syntax
+~~~~~~
+
+The file consists of sections and subkeys. A section begins with
+the name of the section in square brackets and continues until the next
+section begins. Each variable have to belong to some section, which means
+there must be a section header before the first setting of a variable, as below:
+Each variable are in the form 'subkey = value'.
+
+	[section]
+		subkey1 = value1
+		subkey2 = value2
+
+Subsection names are case sensitive and can contain any characters except
+newline (doublequote `"` and backslash have to be escaped as `\"` and `\\`,
+respectively).  Section headers cannot span multiple
+lines.  Variables may belong directly to a section or to a given subsection.
+
+Example
+~~~~~~~
+
+Given a $HOME/.perfconfig like this:
+
+#
+# This is the config file, and
+# a '#' and ';' character indicates a comment
+#
+
+[colors]
+	# Color variables
+	top = red, default
+	medium = green, default
+	normal = lightgray, default
+	selected = white, lightgray
+	code = blue, default
+	addr = magenta, default
+	root = white, blue
+
+[tui]
+	# Defaults if linked with libslang
+	report = on
+	annotate = on
+	top = on
+
+[buildid]
+	# Default, disable using /dev/null
+	dir = /root/.debug
+
+[annotate]
+	# Defaults
+	hide_src_code = false
+	use_offset = true
+	jump_arrows = true
+	show_nr_jumps = false
+
+[help]
+	# Format can be man, info, web or html
+	format = man
+	autocorrect = 0
+
+[ui]
+	show-headers= true
+
+[call-graph]
+	# fp (framepointer), dwarf
+	record-mode = fp
+	print-type = graph
+	order = caller
+	sort-key = function
+
+Variables
+~~~~~~~~~
+
+colors.*::
+	Color variables can appoint colors of the output which is printed out
+	from ‘report’, ‘top’,’annotate’ on tui.
+	Color variables is composed of foreground and background
+	and should have two values for them. If you want to set as colors
+	of your terminal, you should use ‘default’ for color value.
+        The kind of color which can be used as below.
+	red, green, default, black, blue, white, magenta, lightgray
+
+	colors.top::
+		‘top’ means a overhead percentage which has more than 5%.
+		And values of it’s variable specify colors of percentage.
+		Basic key values are foreground-color ’red’ and
+		background-color ’default’.
+	colors.medium::
+		‘medium’ means a overhead percentage which has more than 0.5%.
+		Default values are ’green’ and ’default’.
+	colors.normal::
+		‘normal’ means rest of overhead percentages
+		except ‘top’, ‘medium’, ‘selected’.
+		Default values are ’lightgray’ and ’default’.
+	colors.selected::
+		This appoint colors for forcussed one of the output list
+		from sub-commands (top,report,annotate).
+		Default values are ’white’ and ’lightgray’.
+	colors.code::
+		Colors for a arrow and lines on jumping by assembly code
+		such as ‘jns’,’jmp’,’jane’,etc. Default values are ‘blue’, ‘default’.
+	colors.addr::
+		This appoint colors for addresses from a sub-command ’annotate’.
+		Default values are ‘magenta’, ‘default’.
+	colors.root::
+		Colors for headers in the output of a sub-command ‘top’.
+		Default values are ‘white’, ‘blue’.
+
+tui.*::
+	A boolean value that controls launching TUI browser for each subcommand.
+	By default, TUI is enabled if perf detects a needed library during build
+	and this config option can control it.  Available subcommands are 'top',
+	'report' and 'annotate'.
+
+gtk.*::
+	A boolean value that controls launching GTK+2 GUI browser for
+	each subcommand.  By default, TUI is enabled if perf detects a
+	needed library during build and this config option can control
+	it.  Available subcommands are 'top', 'report' and 'annotate'.
+
+buildid.*::
+	buildid.dir::
+		Each executable or shared library built with each program is assigned
+		a unique identification as build-id. The option means a path where
+		build-id information can be saved.
+		The default is $HOME/.debug
+
+annotate.*::
+	There’re options which work with a ’annotate’ sub-command.
+	This Options is in control of addresses, jump function, source code
+	in lines of assembly code from a specific program.
+
+	annotate.hide_src_code::
+		If a program which is analyzed has source code of itself,
+		this option let ‘annotate’ print a list of assembly code with the source code.
+		For example, let’s see a part of a program. There’re four lines.
+		If this option is ‘false’, they can be printed
+		without source code from a program as below.
+
+		│        push   %rbp
+		│        mov    %rsp,%rbp
+		│        sub    $0x10,%rsp
+		│        mov    (%rdi),%rdx
+
+		But if this option is ‘true’, source code of the part
+		can be also printed as below.
+
+		│      struct rb_node *rb_next(const struct rb_node *node)
+		│      {
+		│        push   %rbp
+		│        mov    %rsp,%rbp
+		│        sub    $0x10,%rsp
+		│              struct rb_node *parent;
+		│
+		│              if (RB_EMPTY_NODE(node))
+		│        mov    (%rdi),%rdx
+		│              return n;
+
+        annotate.use_offset::
+		Basing on a first address of a loaded function, offset can be used.
+		Instead of using original addresses of assembly code,
+		addresses subtracted from a base address can be printed.
+		Let’s illustrate a example.
+		If a base address is 0XFFFFFFFF81624d50 as below,
+
+		ffffffff81624d50 <load0>
+
+		a address on assembly code has a specific absolute address as below
+
+		ffffffff816250b8:│  mov    0x8(%r14),%rdi
+
+		but if use_offset is ’true’, a address subtracted from a base address is printed.
+		The default is true.
+
+		             368:│  mov    0x8(%r14),%rdi
+
+	annotate.jump_arrows::
+		There’re jump instruction among assembly code.
+		Depending on a boolean value of jump_arrows,
+		arrows can be printed or not which represent
+		where do the instruction jump into as below.
+
+		│     ┌──jmp    1333
+		│     │  xchg   %ax,%ax
+		│1330:│  mov    %r15,%r10
+		│1333:└─→cmp    %r15,%r14
+
+		If jump_arrow is ‘false’, the arrows isn’t printed as below.
+
+		│      ↓ jmp    1333
+		│        xchg   %ax,%ax
+		│1330:   mov    %r15,%r10
+		│1333:   cmp    %r15,%r14
+
+        annotate.show_nr_jumps::
+		Let’s see a part of assembly code.
+
+		│1382:   movb   $0x1,-0x270(%rbp)
+
+		If use this, the number of branches branching to that address can be printed as below.
+
+		│1 1382:   movb   $0x1,-0x270(%rbp)
+
+help.*::
+	help.format:: = man
+		A format of manual page can be ‘man’, ‘info’, ‘web’ or ‘html’.
+		’man’ is default.
+	help.autocorrect:: = 0
+		Automatically correct and execute mistyped commands after
+		waiting for the given number of deciseconds (0.1 sec).
+		Let's see a example. If a mistyped sub-command is executed like 'perf mistyped-command'
+		and this option is 0, the output is as below.
+
+		perf: 'mistyped-command' is not a perf-command. See 'perf --help’.
+
+		Or if this option is more than 1, the output can be such as.
+
+		WARNING: You called a perf program named 'mistyped-command', which does not exist.
+		Continuing under the assumption that you meant 'with-kcore'
+		in 0.1 seconds automatically...
+		Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]
+		<perf sub-command> can be record, script, report or inject
+		    or: perf-with-kcore fix_buildid_cache_permissions
+
+hist.*::
+	hist.percentage::
+		This option control a way to calcurate overhead of filtered entries -
+		that means the value of this option is effective only if there's a
+		filter (by comm, dso or symbol name).  Suppose a following example:
+
+		       Overhead  Symbols
+		       ........  .......
+		        33.33%     foo
+		        33.33%     bar
+		        33.33%     baz
+
+	       This is an original overhead and we'll filter out the first 'foo'
+	       entry.  The value of 'relative' would increase the overhead of 'bar'
+	       and 'baz' to 50.00% for each, while 'absolute' would show their
+	       current overhead (33.33%).
+
+ui.*::
+	ui.show-headers::
+		There’re columns as header ‘Overhead’, ‘Children’, ‘Shared Object’, ‘Symbol’, ’self’.
+		If this option is false, they are hiden.
+
+call-graph.*::
+	When sub-commands ‘top’ and ‘report’ work with -g/—-children
+	there’re options in control of call-graph.
+
+	call-graph.record-mode::
+		The record-mode can be ‘fp’ (frame pointer) and ‘dwarf’.
+		The value of 'dwarf' is effective only if perf detect needed library
+		(libunwind or a recent version of libdw).  Also it doesn't *require*
+		the dump-size option since it can use the default value of 8192 if
+		missing.
+
+	call-graph.dump-size::
+		The size of stack to dump in order to do post-unwinding.  Default is 8192 (byte).
+		When using dwarf into record-mode this option should have a value.
+
+	call-graph.print-type::
+		The print-types can be graph (graph absolute), fractal (graph relative), flat.
+		This option controls a way to show overhead for each callchain entry.
+		Suppose a following example.
+
+		Overhead  Symbols
+		........  .......
+		  40.00%  foo
+		      |
+		      --- foo
+		      |
+		      |--50.00%-- bar
+		      |           main
+		      |
+		      --50.00%-- baz
+		                 main
+
+		This output is a default format which is 'fractal'.  The 'foo' came
+		from 'bar' and 'baz' exactly half and half so 'fractal' shows 50.00%
+		for each (meaning that it assumes 100% total overhead of 'foo').
+
+		The 'graph' uses absolute overhead value of 'foo' as total so each of
+		'bar' and 'baz' callchain will have 20.00% of overhead.
+
+	call-graph.order::
+		This option controls print order of callchains.  The default is
+		'callee' which means callee is printed at top and then followed by its
+		caller and so on.  The 'caller' prints it in reverse order.
+
+	call-graph.sort-key::
+		The callchains are merged if they contain same information.
+		The sort-key option determines a way to compare the callchains.
+		A value of 'sort-key' can be 'function' or 'address’.
+		The default is ‘function’.
+
+	call-graph.threshold::
+		When there're many callchains it'd print tons of lines.  So perf omits
+		small callchains under a certain overhead (threshold) and this option
+		control the threashold.  Default is 0.5 (%).
+
+	call-graph.print-limit::
+		This is another way to control the number of callchains printed for a
+		single entry.  Default is 0 which means no limitation.
+
+report.*::
+	report.percent-limit::
+		This one is mostly same as call-graph.threshold but works for
+		histogram entries.  Entries have overhead lower than this percentage
+		will not be printed.  Default is 0.
+		If percent-limit is 70, the output which has percentages of
+		each overhead above 70% can be printed.
+
+	report.queue-size::
+		option to setup the maximum allocation size for session's
+		ordered events queue, if not set there's no default limit
+
+	report.children::
+		The children means that functions called from another function.
+		If the option is true, accumulate callchain of children and show total overhead.
+		For example, there’re three functions like below.
+
+		 void foo(void) {
+		   /* do something */
+		 }
+
+		 void bar(void) {
+		   /* do something */
+		   foo();
+		 }
+
+		 int main(void) {
+		   bar()
+		   return 0;
+		 }
+
+		Defaultly the output of sub-commands such as ’top’, ‘report’ and ‘annotate’
+		depend on a sort of overhead into each functions as below.
+
+		Overhead  Symbol
+		........  .....................
+		  60.00%  foo
+		          |
+		          --- foo
+		              bar
+		              main
+		              __libc_start_main
+
+		  40.00%  bar
+		          |
+		          --- bar
+		              main
+		              __libc_start_main
+
+		But if this option is true, the sort is changed into a sort of
+		overhead into each children group of each function  reciting all functions
+		from a first parent function till a last child function like below.
+		And it requires -g/--call-graph option enabled
+
+		Children      Self  Symbol
+		........  ........  ....................
+		 100.00%     0.00%  __libc_start_main
+		          |
+		          --- __libc_start_main
+
+		 100.00%     0.00%  main
+		          |
+		          --- main
+		              __libc_start_main
+
+		 100.00%    40.00%  bar
+		          |
+		          --- bar
+		              main
+		              __libc_start_main
+
+		  60.00%    60.00%  foo
+		          |
+		          --- foo
+		              bar
+		              main
+		              __libc_start_main
+
+top.*::
+	top.children::
+		This option means same as report.children.
+		So it is true, the output of ‘top’ is rearranged by each overhead into children group.
+
+man.*::
+	man.viewer::
+
+pager.*::
+	pager.report::
+	pager
+
+SEE ALSO
+--------
+linkperf:perf[1]
diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
index 767ea24..853aa20 100644
--- a/tools/perf/Documentation/perfconfig.example
+++ b/tools/perf/Documentation/perfconfig.example
@@ -1,29 +1,72 @@
 [colors]
-
-	# These were the old defaults
-	top = red, lightgray
-	medium = green, lightgray
-	normal = black, lightgray
-	selected = lightgray, magenta
-	code = blue, lightgray
-	addr = magenta, lightgray
+	# There are types of colors which are red,
+	# green, default, black, blue,
+	# white, magenta, lightgray
+	# The default is like below
+	top = red, default
+	medium = green, default
+	normal = lightgray, default
+	selected = white, lightgray
+	code = blue, default
+	addr = magenta, default
+	root = white, blue
 
 [tui]
-
 	# Defaults if linked with libslang
 	report = on
 	annotate = on
 	top = on
 
 [buildid]
-
 	# Default, disable using /dev/null
 	dir = /root/.debug
 
 [annotate]
-
 	# Defaults
 	hide_src_code = false
 	use_offset = true
 	jump_arrows = true
 	show_nr_jumps = false
+
+[gtk]
+	report = off
+	annotate = off
+	#top = off
+
+[pager]
+	# That a 'cmd' is true mean to use "pager or less"
+	cmd = true
+	report = false
+	diff = true
+
+[help]
+	# Format can be man, info, web or html
+	format = man
+	autocorrect = 0
+
+[hist]
+	# a value of 'percentage' can be 'relative' or 'absolute'
+	percentage = absolute
+
+[ui]
+	show-headers= true
+
+[call-graph]
+	# fp (framepointer), dwarf
+	record-mode = fp
+
+	# graph (graph absolute), flat, fractal (graph relative)
+	print-type = fractal
+
+	# caller, callee
+	order = caller
+
+	# function, address
+	sort-key = function
+
+[report]
+	percent-limit = 1
+	children = false
+
+[top]
+	children = true
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
new file mode 100644
index 0000000..7cf6d03
--- /dev/null
+++ b/tools/perf/builtin-config.c
@@ -0,0 +1,71 @@
+/*
+ * builtin-config.c
+ *
+ * Copyright (C) 2015, Taeung Song <treeze.taeung@gmail.com>
+ *
+ */
+#include "builtin.h"
+
+#include "perf.h"
+
+#include "util/cache.h"
+#include "util/parse-options.h"
+#include "util/util.h"
+#include "util/debug.h"
+
+static struct {
+	bool all_action;
+} params;
+
+static const char * const config_usage[] = {
+	"perf config [options]",
+	NULL
+};
+static const struct option config_options[] = {
+	OPT_GROUP("Action"),
+	OPT_BOOLEAN('a', "all", &params.all_action, "print all configurations"),
+	OPT_END()
+};
+
+static void check_argc(int argc, int limit)
+{
+	if (argc >= limit && argc <= limit)
+		return;
+	error("wrong number of arguments");
+	usage_with_options(config_usage, config_options);
+}
+
+static int show_config(const char *key, const char *value,
+			   void *cb __maybe_unused)
+{
+	if (value)
+		printf("%s=%s\n", key, value);
+	else
+		printf("%s\n", key);
+
+	return 0;
+}
+
+int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+	int ret = 0;
+
+	argc = parse_options(argc, argv, config_options, config_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+	if (argc > 0) {
+		if (strcmp(argv[0], "-") == 0) {
+			pr_warning("  Error: '-' is not supported.\n");
+			usage_with_options(config_usage, config_options);
+		}
+	}
+
+	if (argc == 0 || params.all_action) {
+		check_argc(argc, 0);
+		ret = perf_config(show_config, NULL);
+	} else {
+		pr_warning("Error: Unknown argument.\n");
+		usage_with_options(config_usage, config_options);
+	}
+
+	return ret;
+}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 3688ad2..3f871b5 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -17,6 +17,7 @@ extern int cmd_annotate(int argc, const char **argv, const char *prefix);
 extern int cmd_bench(int argc, const char **argv, const char *prefix);
 extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix);
 extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
+extern int cmd_config(int argc, const char **argv, const char *prefix);
 extern int cmd_diff(int argc, const char **argv, const char *prefix);
 extern int cmd_evlist(int argc, const char **argv, const char *prefix);
 extern int cmd_help(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 00fcaf8..acc3ea7 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -9,6 +9,7 @@ perf-buildid-cache		mainporcelain common
 perf-buildid-list		mainporcelain common
 perf-data			mainporcelain common
 perf-diff			mainporcelain common
+perf-config			mainporcelain common
 perf-evlist			mainporcelain common
 perf-inject			mainporcelain common
 perf-kmem			mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index b857fcb..604fa4a 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -37,6 +37,7 @@ struct cmd_struct {
 static struct cmd_struct commands[] = {
 	{ "buildid-cache", cmd_buildid_cache, 0 },
 	{ "buildid-list", cmd_buildid_list, 0 },
+	{ "config",	cmd_config,	0 },
 	{ "diff",	cmd_diff,	0 },
 	{ "evlist",	cmd_evlist,	0 },
 	{ "help",	cmd_help,	0 },
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/2] perf tools: Add a option 'remove' to perf-config and features which get or set a config variable.
  2015-04-12 14:44 [PATCH 1/2] perf tools: Add 'perf-config' command Taeung Song
@ 2015-04-12 14:44 ` Taeung Song
  2015-04-13  6:55   ` Namhyung Kim
  2015-04-13  6:16 ` [PATCH 1/2] perf tools: Add 'perf-config' command Namhyung Kim
  1 sibling, 1 reply; 12+ messages in thread
From: Taeung Song @ 2015-04-12 14:44 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: linux-kernel, jolsa, namhyung, Taeung Song

This patch consists of adding functions
which get, set or remove a specific config variable.
For the syntax examples,

   perf config [options] [section.subkey[=value]]

   display a specific key(section.subkey) and value
   # perf config report.queue

   set a specific key and value
   # perf config report.queue=100M

   remove a specific key
   # perf config -r | --remove report.queue

Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
 tools/perf/Documentation/perf-config.txt |   8 ++
 tools/perf/builtin-config.c              | 224 ++++++++++++++++++++++++++++++-
 tools/perf/util/cache.h                  |  17 +++
 tools/perf/util/config.c                 |  35 ++++-
 4 files changed, 278 insertions(+), 6 deletions(-)

diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index b251702..7354b18 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -8,7 +8,11 @@ perf-config - Get and set variables in configuration file.
 SYNOPSIS
 --------
 [verse]
+'perf config' section.subkey[=value]
+or
 'perf config' -a | --all
+or
+'perf config' -r | --remove section.subkey
 
 DESCRIPTION
 -----------
@@ -21,6 +25,10 @@ OPTIONS
 --all::
 	Show all variables with key and value into each sections.
 
+-r::
+--remove::
+	Remove a specific variable.
+
 CONFIGURATION FILE
 ------------------
 
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 7cf6d03..205e053 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -15,15 +15,24 @@
 
 static struct {
 	bool all_action;
+	bool get_action;
+	bool set_action;
+	bool remove_action;
 } params;
 
+LIST_HEAD(sections);
+static char *given_section_name;
+static char *given_subkey;
+static char *given_value;
+
 static const char * const config_usage[] = {
-	"perf config [options]",
+	"perf config [options] [section.subkey[=value]]",
 	NULL
 };
 static const struct option config_options[] = {
 	OPT_GROUP("Action"),
 	OPT_BOOLEAN('a', "all", &params.all_action, "print all configurations"),
+	OPT_BOOLEAN('r', "remove", &params.remove_action, "remove a variable: section.subkey"),
 	OPT_END()
 };
 
@@ -35,6 +44,72 @@ static void check_argc(int argc, int limit)
 	usage_with_options(config_usage, config_options);
 }
 
+static struct config_section *find_config_section(const char *section_name)
+{
+	struct config_section *section_node;
+	list_for_each_entry(section_node, &sections, list)
+		if (!strcmp(section_node->name, section_name))
+			return section_node;
+
+	return NULL;
+}
+
+static struct config_element *find_config_element(const char *subkey
+						  , struct config_section *section_node)
+{
+	struct config_element *element_node;
+
+	list_for_each_entry(element_node, &section_node->element_head, list)
+		if (!strcmp(element_node->subkey, subkey))
+			return element_node;
+
+	return NULL;
+}
+
+static struct config_section *init_config_section(const char *section_name)
+{
+	struct config_section *section_node;
+	LIST_HEAD(element_head);
+
+	section_node = zalloc(sizeof(*section_node));
+	if (!section_node)
+		return NULL;
+
+	INIT_LIST_HEAD(&section_node->element_head);
+	list_splice(&element_head, &section_node->element_head);
+	section_node->name = strdup(section_name);
+	if (!section_node->name) {
+		pr_err("%s: strdup failed\n", __func__);
+		return NULL;
+	}
+
+	return section_node;
+}
+
+static int add_config_element(struct list_head *head
+			      , const char *subkey, const char *value)
+{
+	struct config_element *element_node;
+	element_node = zalloc(sizeof(*element_node));
+	element_node->subkey = strdup(subkey);
+	if (!element_node->subkey) {
+		pr_err("%s: strdup failed\n", __func__);
+		return -1;
+	}
+	if (value) {
+		element_node->value = strdup(value);
+		if (!element_node->value) {
+			pr_err("%s: strdup failed\n", __func__);
+			return -1;
+		}
+	} else
+		element_node->value = NULL;
+
+	list_add_tail(&element_node->list, head);
+
+	return 0;
+}
+
 static int show_config(const char *key, const char *value,
 			   void *cb __maybe_unused)
 {
@@ -46,22 +121,165 @@ static int show_config(const char *key, const char *value,
 	return 0;
 }
 
+static int show_spec_config(struct config_section *section_node
+			    , struct config_element *element_node)
+{
+	char key[BUFSIZ];
+
+	if (section_node && element_node) {
+		sprintf(key, "%s.%s", section_node->name, element_node->subkey);
+		show_config(key, element_node->value, NULL);
+	} else
+		pr_err("Error: Failed to find the variable.\n");
+
+	return 0;
+}
+
+static int set_config(struct config_section *section_node, struct config_element *element_node)
+{
+	if (!given_value) {
+		/* value == NULL means remove the variable */
+		if (section_node && element_node)
+			element_node->value = NULL;
+		else /* do nothing */
+			return 0;
+	} else {
+		/* if there isn't existent section, add a new section */
+		if (!section_node) {
+			section_node = init_config_section(given_section_name);
+			if (!section_node)
+				return -1;
+			list_add_tail(&section_node->list, &sections);
+		}
+		/* if nothing to replace, add a new element which contains key-value pair. */
+		if (!element_node)
+			add_config_element(&section_node->element_head, given_subkey, given_value);
+		else
+			element_node->value = given_value;
+	}
+
+	perf_configset_write_in_full();
+
+	return 0;
+}
+
+static int collect_config(const char *var, const char *value
+			  , void *cb __maybe_unused)
+{
+	struct config_section *section_node;
+	char *section_name, *subkey;
+	char *key = strdup(var);
+
+	if (!key) {
+		pr_err("%s: strdup failed\n", __func__);
+		return -1;
+	}
+	section_name = strsep(&key, ".");
+	subkey = strsep(&key, ".");
+	section_node = find_config_section(section_name);
+	if (!section_node) {
+		/* Add a new section */
+		section_node = init_config_section(section_name);
+		if (!section_node)
+			return -1;
+		list_add_tail(&section_node->list, &sections);
+	}
+
+	add_config_element(&section_node->element_head, subkey, value);
+
+	return 0;
+}
+
+static int perf_configset_with_option(configset_fn_t fn, const char *var)
+{
+	struct config_section *section_node = NULL;
+	struct config_element *element_node = NULL;
+	char *key = strdup(var);
+	const char *last_dot = strrchr(key, '.');
+	/*
+	 * Since "key" actually contains the section name and the real
+	 * key name separated by a dot, we have to know where the dot is.
+	 */
+	if (last_dot == NULL || last_dot == key) {
+		pr_err("The config variable does not contain a section: %s\n", key);
+		return -1;
+	}
+	if (!last_dot[1]) {
+		pr_err("The config varible does not contain variable name: %s\n", key);
+		return -1;
+	}
+
+	given_value = strrchr(key, '=');
+	if (given_value == NULL || given_value == key)
+		given_value = NULL;
+	else {
+		if (!given_value[1]) {
+			pr_err("The config variable does not contain a value: %s\n", key);
+			return -1;
+		} else
+			given_value++;
+	}
+	given_section_name = strsep(&key, ".");
+	given_subkey = strsep(&key, ".");
+	if (strsep(&key, ".") != NULL)
+		return -1;
+	if (given_value)
+		given_subkey = strsep(&given_subkey, "=");
+
+	perf_config(collect_config, NULL);
+
+	section_node = find_config_section(given_section_name);
+
+	if (section_node != NULL)
+		element_node = find_config_element(given_subkey, section_node);
+
+	fn(section_node, element_node);
+
+	return 0;
+}
+
 int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	int ret = 0;
+	int origin_argc = argc - 1;
+	char *value;
+	bool is_option;
 
 	argc = parse_options(argc, argv, config_options, config_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
-	if (argc > 0) {
+	if (origin_argc > argc)
+		is_option = true;
+	else
+		is_option = false;
+
+	if (!is_option && argc > 0) {
 		if (strcmp(argv[0], "-") == 0) {
 			pr_warning("  Error: '-' is not supported.\n");
 			usage_with_options(config_usage, config_options);
 		}
+
+		switch (argc) {
+		case 1:
+			value = strrchr(argv[0], '=');
+			if (value == NULL || value == argv[0])
+				params.get_action = true;
+			else
+				params.set_action = true;
+			break;
+		default:
+			break;
+		}
 	}
 
-	if (argc == 0 || params.all_action) {
+	if ((!is_option && argc == 0) || params.all_action) {
 		check_argc(argc, 0);
 		ret = perf_config(show_config, NULL);
+	} else if (params.get_action) {
+		check_argc(argc, 1);
+		ret = perf_configset_with_option(show_spec_config, argv[0]);
+	} else if (params.set_action || params.remove_action) {
+		check_argc(argc, 1);
+		ret = perf_configset_with_option(set_config, argv[0]);
 	} else {
 		pr_warning("Error: Unknown argument.\n");
 		usage_with_options(config_usage, config_options);
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index fbcca21..17b271f 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -1,6 +1,7 @@
 #ifndef __PERF_CACHE_H
 #define __PERF_CACHE_H
 
+#include <linux/list.h>
 #include <stdbool.h>
 #include "util.h"
 #include "strbuf.h"
@@ -19,6 +20,22 @@
 #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
 #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
 
+struct config_element {
+	char *subkey;
+	char *value;
+	struct list_head list;
+};
+
+struct config_section {
+	char *name;
+	struct list_head element_head;
+	struct list_head list;
+};
+
+extern struct list_head sections;
+
+typedef int (*configset_fn_t)(struct config_section *, struct config_element *);
+extern int perf_configset_write_in_full(void);
 typedef int (*config_fn_t)(const char *, const char *, void *);
 extern int perf_default_config(const char *, const char *, void *);
 extern int perf_config(config_fn_t fn, void *);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index e18f653..ffcbe96 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -21,7 +21,7 @@
 char buildid_dir[MAXPATHLEN]; /* root dir for buildid, binary cache */
 
 static FILE *config_file;
-static const char *config_file_name;
+static char *config_file_name;
 static int config_linenr;
 static int config_file_eof;
 
@@ -420,12 +420,11 @@ static int perf_config_from_file(config_fn_t fn, const char *filename, void *dat
 	ret = -1;
 	if (f) {
 		config_file = f;
-		config_file_name = filename;
+		config_file_name = strdup(filename);
 		config_linenr = 1;
 		config_file_eof = 0;
 		ret = perf_parse_file(fn, data);
 		fclose(f);
-		config_file_name = NULL;
 	}
 	return ret;
 }
@@ -502,6 +501,36 @@ out:
 	return ret;
 }
 
+int perf_configset_write_in_full(void)
+{
+	struct config_section *section_node;
+	struct config_element *element_node;
+	char section[BUFSIZ];
+	char key_value_pair[BUFSIZ];
+	const char *first_line = "# this file is auto-generated.\n";
+	FILE *f = fopen(config_file_name, "w");
+
+	if (!f)
+		return -1;
+
+	fwrite(first_line, strlen(first_line), 1, f);
+	/* overwrite configvariables */
+	list_for_each_entry(section_node, &sections, list) {
+		sprintf(section, "[%s]\n", section_node->name);
+		fwrite(section, strlen(section), 1, f);
+		list_for_each_entry(element_node, &section_node->element_head, list) {
+			if (element_node->value) {
+				sprintf(key_value_pair, "\t%s = %s\n"
+					, element_node->subkey, element_node->value);
+				fwrite(key_value_pair, strlen(key_value_pair), 1, f);
+			}
+		}
+	}
+	fclose(f);
+
+	return 0;
+}
+
 /*
  * Call this to report error for your variable that should not
  * get a boolean value (i.e. "[my] var" means "true").
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/2] perf tools: Add 'perf-config' command
  2015-04-12 14:44 [PATCH 1/2] perf tools: Add 'perf-config' command Taeung Song
  2015-04-12 14:44 ` [PATCH 2/2] perf tools: Add a option 'remove' to perf-config and features which get or set a config variable Taeung Song
@ 2015-04-13  6:16 ` Namhyung Kim
       [not found]   ` <5CB87CAF-B6EE-4AE0-BC3C-45CEF14C28EC@gmail.com>
       [not found]   ` <70EA4387-5059-4026-8819-039474865EEE@gmail.com>
  1 sibling, 2 replies; 12+ messages in thread
From: Namhyung Kim @ 2015-04-13  6:16 UTC (permalink / raw)
  To: Taeung Song; +Cc: Arnaldo Carvalho de Melo, linux-kernel, jolsa

Hi Taeung,

On Sun, Apr 12, 2015 at 11:44:48PM +0900, Taeung Song wrote:
> The perf configuration file contains many variables which can make
> the perf command's action more effective and more skilful.
> But looking through state of configuration is difficult and
> there's no knowing what kind of other variables except variables in perfconfig.example exist.
> So This patch adds 'perf-config' command with '--all' option and a document for it.
> 
> Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
> ---

Thanks for your work!

I think the documentation updates need to be shared with tools
manpages, or at least they can point to this document for details.
This can be further work though. ;-)


[SNIP]
> diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
> new file mode 100644
> index 0000000..7cf6d03
> --- /dev/null
> +++ b/tools/perf/builtin-config.c
> @@ -0,0 +1,71 @@
> +/*
> + * builtin-config.c
> + *
> + * Copyright (C) 2015, Taeung Song <treeze.taeung@gmail.com>
> + *
> + */
> +#include "builtin.h"
> +
> +#include "perf.h"
> +
> +#include "util/cache.h"
> +#include "util/parse-options.h"
> +#include "util/util.h"
> +#include "util/debug.h"
> +
> +static struct {
> +	bool all_action;
> +} params;
> +
> +static const char * const config_usage[] = {
> +	"perf config [options]",
> +	NULL
> +};
> +static const struct option config_options[] = {
> +	OPT_GROUP("Action"),
> +	OPT_BOOLEAN('a', "all", &params.all_action, "print all configurations"),
> +	OPT_END()
> +};
> +
> +static void check_argc(int argc, int limit)
> +{
> +	if (argc >= limit && argc <= limit)
> +		return;
> +	error("wrong number of arguments");
> +	usage_with_options(config_usage, config_options);
> +}

I don't know why this is needed.  The -a option won't need this and we
can support to get/set any number of config items IMHO.


> +
> +static int show_config(const char *key, const char *value,
> +			   void *cb __maybe_unused)
> +{
> +	if (value)
> +		printf("%s=%s\n", key, value);
> +	else
> +		printf("%s\n", key);
> +
> +	return 0;
> +}
> +
> +int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
> +{
> +	int ret = 0;
> +
> +	argc = parse_options(argc, argv, config_options, config_usage,
> +			     PARSE_OPT_STOP_AT_NON_OPTION);
> +	if (argc > 0) {
> +		if (strcmp(argv[0], "-") == 0) {
> +			pr_warning("  Error: '-' is not supported.\n");

I don't understand this.  Why is the "-" so special?

And I think current behavior don't allow any argument.  So what about this?

	argc = parse_options(...);
	if (argc)
		usage_with_options(...);

	if (params.all_action)
		...


> +			usage_with_options(config_usage, config_options);
> +		}
> +	}
> +
> +	if (argc == 0 || params.all_action) {
> +		check_argc(argc, 0);
> +		ret = perf_config(show_config, NULL);

But doesn't it just print currently set items in a config file?  I
guess -a/--all option should show this *AND* all possible config items
with default values.  Current behavior can be done by -l/--list option
like git-config..

Thanks,
Namhyung


> +	} else {
> +		pr_warning("Error: Unknown argument.\n");
> +		usage_with_options(config_usage, config_options);
> +	}
> +
> +	return ret;
> +}
> diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
> index 3688ad2..3f871b5 100644
> --- a/tools/perf/builtin.h
> +++ b/tools/perf/builtin.h
> @@ -17,6 +17,7 @@ extern int cmd_annotate(int argc, const char **argv, const char *prefix);
>  extern int cmd_bench(int argc, const char **argv, const char *prefix);
>  extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix);
>  extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
> +extern int cmd_config(int argc, const char **argv, const char *prefix);
>  extern int cmd_diff(int argc, const char **argv, const char *prefix);
>  extern int cmd_evlist(int argc, const char **argv, const char *prefix);
>  extern int cmd_help(int argc, const char **argv, const char *prefix);
> diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
> index 00fcaf8..acc3ea7 100644
> --- a/tools/perf/command-list.txt
> +++ b/tools/perf/command-list.txt
> @@ -9,6 +9,7 @@ perf-buildid-cache		mainporcelain common
>  perf-buildid-list		mainporcelain common
>  perf-data			mainporcelain common
>  perf-diff			mainporcelain common
> +perf-config			mainporcelain common
>  perf-evlist			mainporcelain common
>  perf-inject			mainporcelain common
>  perf-kmem			mainporcelain common
> diff --git a/tools/perf/perf.c b/tools/perf/perf.c
> index b857fcb..604fa4a 100644
> --- a/tools/perf/perf.c
> +++ b/tools/perf/perf.c
> @@ -37,6 +37,7 @@ struct cmd_struct {
>  static struct cmd_struct commands[] = {
>  	{ "buildid-cache", cmd_buildid_cache, 0 },
>  	{ "buildid-list", cmd_buildid_list, 0 },
> +	{ "config",	cmd_config,	0 },
>  	{ "diff",	cmd_diff,	0 },
>  	{ "evlist",	cmd_evlist,	0 },
>  	{ "help",	cmd_help,	0 },
> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] perf tools: Add a option 'remove' to perf-config and features which get or set a config variable.
  2015-04-12 14:44 ` [PATCH 2/2] perf tools: Add a option 'remove' to perf-config and features which get or set a config variable Taeung Song
@ 2015-04-13  6:55   ` Namhyung Kim
       [not found]     ` <6F8981BC-A058-4D84-93FC-B7CB8ADDCC53@gmail.com>
  0 siblings, 1 reply; 12+ messages in thread
From: Namhyung Kim @ 2015-04-13  6:55 UTC (permalink / raw)
  To: Taeung Song; +Cc: Arnaldo Carvalho de Melo, linux-kernel, jolsa

On Sun, Apr 12, 2015 at 11:44:49PM +0900, Taeung Song wrote:
> This patch consists of adding functions
> which get, set or remove a specific config variable.
> For the syntax examples,
> 
>    perf config [options] [section.subkey[=value]]
> 
>    display a specific key(section.subkey) and value
>    # perf config report.queue
> 
>    set a specific key and value
>    # perf config report.queue=100M
> 
>    remove a specific key
>    # perf config -r | --remove report.queue
> 
> Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
> ---
>  tools/perf/Documentation/perf-config.txt |   8 ++
>  tools/perf/builtin-config.c              | 224 ++++++++++++++++++++++++++++++-
>  tools/perf/util/cache.h                  |  17 +++
>  tools/perf/util/config.c                 |  35 ++++-
>  4 files changed, 278 insertions(+), 6 deletions(-)
> 
> diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
> index b251702..7354b18 100644
> --- a/tools/perf/Documentation/perf-config.txt
> +++ b/tools/perf/Documentation/perf-config.txt
> @@ -8,7 +8,11 @@ perf-config - Get and set variables in configuration file.
>  SYNOPSIS
>  --------
>  [verse]
> +'perf config' section.subkey[=value]
> +or
>  'perf config' -a | --all
> +or
> +'perf config' -r | --remove section.subkey

I'd like to suggest to split -r option handling into a separate patch.


>  
>  DESCRIPTION
>  -----------
> @@ -21,6 +25,10 @@ OPTIONS
>  --all::
>  	Show all variables with key and value into each sections.
>  
> +-r::
> +--remove::
> +	Remove a specific variable.
> +
>  CONFIGURATION FILE
>  ------------------
>  
> diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
> index 7cf6d03..205e053 100644
> --- a/tools/perf/builtin-config.c
> +++ b/tools/perf/builtin-config.c
> @@ -15,15 +15,24 @@
>  
>  static struct {
>  	bool all_action;
> +	bool get_action;
> +	bool set_action;
> +	bool remove_action;
>  } params;
>  
> +LIST_HEAD(sections);
> +static char *given_section_name;
> +static char *given_subkey;
> +static char *given_value;

Why this given_* variables are needed?  I think they can be passed
simply via function arguments?


> +
>  static const char * const config_usage[] = {
> -	"perf config [options]",
> +	"perf config [options] [section.subkey[=value]]",
>  	NULL
>  };
>  static const struct option config_options[] = {
>  	OPT_GROUP("Action"),
>  	OPT_BOOLEAN('a', "all", &params.all_action, "print all configurations"),
> +	OPT_BOOLEAN('r', "remove", &params.remove_action, "remove a variable: section.subkey"),
>  	OPT_END()
>  };
>  
> @@ -35,6 +44,72 @@ static void check_argc(int argc, int limit)
>  	usage_with_options(config_usage, config_options);
>  }
>  
> +static struct config_section *find_config_section(const char *section_name)
> +{
> +	struct config_section *section_node;

It'd be better to split declaration and function body with a blank line.


> +	list_for_each_entry(section_node, &sections, list)
> +		if (!strcmp(section_node->name, section_name))
> +			return section_node;
> +
> +	return NULL;
> +}
> +
> +static struct config_element *find_config_element(const char *subkey
> +						  , struct config_section *section_node)
> +{
> +	struct config_element *element_node;
> +
> +	list_for_each_entry(element_node, &section_node->element_head, list)
> +		if (!strcmp(element_node->subkey, subkey))
> +			return element_node;
> +
> +	return NULL;
> +}
> +
> +static struct config_section *init_config_section(const char *section_name)
> +{
> +	struct config_section *section_node;
> +	LIST_HEAD(element_head);
> +
> +	section_node = zalloc(sizeof(*section_node));
> +	if (!section_node)
> +		return NULL;
> +
> +	INIT_LIST_HEAD(&section_node->element_head);
> +	list_splice(&element_head, &section_node->element_head);

I don't see why this additional element_head is needed?


> +	section_node->name = strdup(section_name);
> +	if (!section_node->name) {
> +		pr_err("%s: strdup failed\n", __func__);
> +		return NULL;
> +	}
> +
> +	return section_node;
> +}
> +
> +static int add_config_element(struct list_head *head
> +			      , const char *subkey, const char *value)
> +{
> +	struct config_element *element_node;
> +	element_node = zalloc(sizeof(*element_node));
> +	element_node->subkey = strdup(subkey);
> +	if (!element_node->subkey) {

You need to free all previously allocated memory (i.e. the element_node).


> +		pr_err("%s: strdup failed\n", __func__);
> +		return -1;
> +	}
> +	if (value) {
> +		element_node->value = strdup(value);
> +		if (!element_node->value) {

Ditto.


> +			pr_err("%s: strdup failed\n", __func__);
> +			return -1;
> +		}
> +	} else
> +		element_node->value = NULL;
> +
> +	list_add_tail(&element_node->list, head);
> +
> +	return 0;
> +}
> +
>  static int show_config(const char *key, const char *value,
>  			   void *cb __maybe_unused)
>  {
> @@ -46,22 +121,165 @@ static int show_config(const char *key, const char *value,
>  	return 0;
>  }
>  
> +static int show_spec_config(struct config_section *section_node
> +			    , struct config_element *element_node)
> +{
> +	char key[BUFSIZ];
> +
> +	if (section_node && element_node) {
> +		sprintf(key, "%s.%s", section_node->name, element_node->subkey);

Please use scnprintf() instead of sprintf().


> +		show_config(key, element_node->value, NULL);
> +	} else
> +		pr_err("Error: Failed to find the variable.\n");
> +
> +	return 0;
> +}
> +
> +static int set_config(struct config_section *section_node, struct config_element *element_node)
> +{
> +	if (!given_value) {
> +		/* value == NULL means remove the variable */
> +		if (section_node && element_node)
> +			element_node->value = NULL;
> +		else /* do nothing */
> +			return 0;
> +	} else {
> +		/* if there isn't existent section, add a new section */
> +		if (!section_node) {
> +			section_node = init_config_section(given_section_name);
> +			if (!section_node)
> +				return -1;
> +			list_add_tail(&section_node->list, &sections);
> +		}
> +		/* if nothing to replace, add a new element which contains key-value pair. */
> +		if (!element_node)
> +			add_config_element(&section_node->element_head, given_subkey, given_value);
> +		else
> +			element_node->value = given_value;
> +	}
> +
> +	perf_configset_write_in_full();
> +
> +	return 0;
> +}
> +
> +static int collect_config(const char *var, const char *value
> +			  , void *cb __maybe_unused)
> +{
> +	struct config_section *section_node;
> +	char *section_name, *subkey;
> +	char *key = strdup(var);
> +
> +	if (!key) {
> +		pr_err("%s: strdup failed\n", __func__);
> +		return -1;
> +	}
> +	section_name = strsep(&key, ".");
> +	subkey = strsep(&key, ".");
> +	section_node = find_config_section(section_name);
> +	if (!section_node) {
> +		/* Add a new section */
> +		section_node = init_config_section(section_name);
> +		if (!section_node)
> +			return -1;
> +		list_add_tail(&section_node->list, &sections);
> +	}
> +
> +	add_config_element(&section_node->element_head, subkey, value);
> +
> +	return 0;
> +}
> +
> +static int perf_configset_with_option(configset_fn_t fn, const char *var)
> +{
> +	struct config_section *section_node = NULL;
> +	struct config_element *element_node = NULL;
> +	char *key = strdup(var);

Need to check return value here.


> +	const char *last_dot = strrchr(key, '.');
> +	/*
> +	 * Since "key" actually contains the section name and the real
> +	 * key name separated by a dot, we have to know where the dot is.
> +	 */
> +	if (last_dot == NULL || last_dot == key) {
> +		pr_err("The config variable does not contain a section: %s\n", key);
> +		return -1;
> +	}
> +	if (!last_dot[1]) {
> +		pr_err("The config varible does not contain variable name: %s\n", key);
> +		return -1;
> +	}
> +
> +	given_value = strrchr(key, '=');

I think it should be strchr so that it can find first '=' character
instead of the last one in case the given_value contains the '=' like
env variables.


> +	if (given_value == NULL || given_value == key)
> +		given_value = NULL;
> +	else {
> +		if (!given_value[1]) {
> +			pr_err("The config variable does not contain a value: %s\n", key);
> +			return -1;
> +		} else
> +			given_value++;
> +	}
> +	given_section_name = strsep(&key, ".");
> +	given_subkey = strsep(&key, ".");
> +	if (strsep(&key, ".") != NULL)
> +		return -1;
> +	if (given_value)
> +		given_subkey = strsep(&given_subkey, "=");
> +
> +	perf_config(collect_config, NULL);
> +
> +	section_node = find_config_section(given_section_name);
> +
> +	if (section_node != NULL)
> +		element_node = find_config_element(given_subkey, section_node);
> +
> +	fn(section_node, element_node);

Here, given_section, subkey and value can be passed.


> +
> +	return 0;
> +}
> +
>  int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
>  {
>  	int ret = 0;
> +	int origin_argc = argc - 1;
> +	char *value;
> +	bool is_option;
>  
>  	argc = parse_options(argc, argv, config_options, config_usage,
>  			     PARSE_OPT_STOP_AT_NON_OPTION);
> -	if (argc > 0) {
> +	if (origin_argc > argc)
> +		is_option = true;
> +	else
> +		is_option = false;
> +
> +	if (!is_option && argc > 0) {
>  		if (strcmp(argv[0], "-") == 0) {
>  			pr_warning("  Error: '-' is not supported.\n");
>  			usage_with_options(config_usage, config_options);
>  		}
> +
> +		switch (argc) {
> +		case 1:
> +			value = strrchr(argv[0], '=');
> +			if (value == NULL || value == argv[0])
> +				params.get_action = true;
> +			else
> +				params.set_action = true;
> +			break;
> +		default:
> +			break;
> +		}
>  	}
>  
> -	if (argc == 0 || params.all_action) {
> +	if ((!is_option && argc == 0) || params.all_action) {
>  		check_argc(argc, 0);
>  		ret = perf_config(show_config, NULL);
> +	} else if (params.get_action) {
> +		check_argc(argc, 1);
> +		ret = perf_configset_with_option(show_spec_config, argv[0]);
> +	} else if (params.set_action || params.remove_action) {
> +		check_argc(argc, 1);
> +		ret = perf_configset_with_option(set_config, argv[0]);
>  	} else {
>  		pr_warning("Error: Unknown argument.\n");
>  		usage_with_options(config_usage, config_options);
> diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
> index fbcca21..17b271f 100644
> --- a/tools/perf/util/cache.h
> +++ b/tools/perf/util/cache.h
> @@ -1,6 +1,7 @@
>  #ifndef __PERF_CACHE_H
>  #define __PERF_CACHE_H
>  
> +#include <linux/list.h>
>  #include <stdbool.h>
>  #include "util.h"
>  #include "strbuf.h"
> @@ -19,6 +20,22 @@
>  #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
>  #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
>  
> +struct config_element {
> +	char *subkey;
> +	char *value;
> +	struct list_head list;
> +};
> +
> +struct config_section {
> +	char *name;
> +	struct list_head element_head;
> +	struct list_head list;
> +};
> +
> +extern struct list_head sections;
> +
> +typedef int (*configset_fn_t)(struct config_section *, struct config_element *);
> +extern int perf_configset_write_in_full(void);
>  typedef int (*config_fn_t)(const char *, const char *, void *);
>  extern int perf_default_config(const char *, const char *, void *);
>  extern int perf_config(config_fn_t fn, void *);
> diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
> index e18f653..ffcbe96 100644
> --- a/tools/perf/util/config.c
> +++ b/tools/perf/util/config.c
> @@ -21,7 +21,7 @@
>  char buildid_dir[MAXPATHLEN]; /* root dir for buildid, binary cache */
>  
>  static FILE *config_file;
> -static const char *config_file_name;
> +static char *config_file_name;
>  static int config_linenr;
>  static int config_file_eof;
>  
> @@ -420,12 +420,11 @@ static int perf_config_from_file(config_fn_t fn, const char *filename, void *dat
>  	ret = -1;
>  	if (f) {
>  		config_file = f;
> -		config_file_name = filename;
> +		config_file_name = strdup(filename);
>  		config_linenr = 1;
>  		config_file_eof = 0;
>  		ret = perf_parse_file(fn, data);
>  		fclose(f);
> -		config_file_name = NULL;
>  	}
>  	return ret;
>  }
> @@ -502,6 +501,36 @@ out:
>  	return ret;
>  }
>  
> +int perf_configset_write_in_full(void)
> +{
> +	struct config_section *section_node;
> +	struct config_element *element_node;
> +	char section[BUFSIZ];
> +	char key_value_pair[BUFSIZ];
> +	const char *first_line = "# this file is auto-generated.\n";
> +	FILE *f = fopen(config_file_name, "w");
> +
> +	if (!f)
> +		return -1;
> +
> +	fwrite(first_line, strlen(first_line), 1, f);
> +	/* overwrite configvariables */
> +	list_for_each_entry(section_node, &sections, list) {
> +		sprintf(section, "[%s]\n", section_node->name);
> +		fwrite(section, strlen(section), 1, f);

Why not calling fprintf() directly?


> +		list_for_each_entry(element_node, &section_node->element_head, list) {
> +			if (element_node->value) {
> +				sprintf(key_value_pair, "\t%s = %s\n"
> +					, element_node->subkey, element_node->value);
> +				fwrite(key_value_pair, strlen(key_value_pair), 1, f);

Ditto..

Thanks,
Namhyung


> +			}
> +		}
> +	}
> +	fclose(f);
> +
> +	return 0;
> +}
> +
>  /*
>   * Call this to report error for your variable that should not
>   * get a boolean value (i.e. "[my] var" means "true").
> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/2] perf tools: Add 'perf-config' command
       [not found]   ` <5CB87CAF-B6EE-4AE0-BC3C-45CEF14C28EC@gmail.com>
@ 2015-04-19  3:27     ` Namhyung Kim
  0 siblings, 0 replies; 12+ messages in thread
From: Namhyung Kim @ 2015-04-19  3:27 UTC (permalink / raw)
  To: Taewoong Song; +Cc: Arnaldo Carvalho de Melo, linux-kernel, jolsa

Hi Taeung,

On Sat, Apr 18, 2015 at 02:02:08PM +0900, Taewoong Song wrote:
> Hi, Namhyung
> 
> Thanks for your review and advices :)
> There is a question which may be weird, followed by
> 
> > On Apr 13, 2015, at 3:16 PM, Namhyung Kim <namhyung@kernel.org> wrote:
> > 
> > Hi Taeung,
> > 
> > On Sun, Apr 12, 2015 at 11:44:48PM +0900, Taeung Song wrote:
> >> The perf configuration file contains many variables which can make
> >> the perf command's action more effective and more skilful.
> >> But looking through state of configuration is difficult and
> >> there's no knowing what kind of other variables except variables in perfconfig.example exist.
> >> So This patch adds 'perf-config' command with '--all' option and a document for it.
> >> 
> >> Signed-off-by: Taeung Song <treeze.taeung@gmail.com <mailto:treeze.taeung@gmail.com>>
> >> ---
> > 
> > Thanks for your work!
> > 
> > I think the documentation updates need to be shared with tools
> > manpages, or at least they can point to this document for details.
> > This can be further work though. ;-)
> > 
> 
> Sorry I don’t understand this share very well.
> How can I share the documentation with tools manpages ?

I mean you can add a description for some feature to link the config
document or vice versa.  Many of those description can be added to the
tool manpage or cross-reference config option at least.

For example, I sent a patch for children overhead documentation so you
can just add 'see perf-report(1) for more details' into the
description of the config option instead of repeating the whole
contents.  Or use asciidoc's 'include' macro to include the (part of)
doc directly if possible.


> 
> And are there people who can help the document to be modified with more detail info ?
> Are they contributors for doc ?

Unfortunately, very few people donated their time to improve the
documentation until now.

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/2] perf tools: Add 'perf-config' command
       [not found]   ` <70EA4387-5059-4026-8819-039474865EEE@gmail.com>
@ 2015-04-19  3:34     ` Namhyung Kim
  0 siblings, 0 replies; 12+ messages in thread
From: Namhyung Kim @ 2015-04-19  3:34 UTC (permalink / raw)
  To: Taewoong Song; +Cc: Arnaldo Carvalho de Melo, linux-kernel, jolsa

On Sat, Apr 18, 2015 at 07:14:06PM +0900, Taewoong Song wrote:
> > On Apr 13, 2015, at 3:16 PM, Namhyung Kim <namhyung@kernel.org> wrote:
> > On Sun, Apr 12, 2015 at 11:44:48PM +0900, Taeung Song wrote:
> >> +static void check_argc(int argc, int limit)
> >> +{
> >> +	if (argc >= limit && argc <= limit)
> >> +		return;
> >> +	error("wrong number of arguments");
> >> +	usage_with_options(config_usage, config_options);
> >> +}
> > 
> > I don't know why this is needed.  The -a option won't need this and we
> > can support to get/set any number of config items IMHO.
> > 
> 
> I also think we can support to get/set any number of config items.
> But I think that ‘—list’ or  ‘—all’ can need to be checked to validate argument.
> If work ‘git —list’ with other argument, error message can be printed like this.
> 
> :> git config --list 134 
> error: wrong number of arguments 
> usage: git config [options] 
> 
> Config file location 
> 	--global use global config file
> 	--system use system config file
> 	--local use repository config file 
> 	-f, --file <file> use given config file
> 	--blob <blob-id> read config from given blob object
> 
> …(omitted)…
> 
> If don’t checking number of argument, we allow users to work a optio
> ‘-a’ or ‘-l’ with other arguments which can be weor meaningless.
> Did I misunderstand what you say?
> Or is there other way to avoid this problem ?

Then just check 'argc != 0' for -l or -a cases.  The get/set won't
need it IMHO.

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] perf tools: Add a option 'remove' to perf-config and features which get or set a config variable.
       [not found]     ` <6F8981BC-A058-4D84-93FC-B7CB8ADDCC53@gmail.com>
@ 2015-04-19  3:42       ` Namhyung Kim
  0 siblings, 0 replies; 12+ messages in thread
From: Namhyung Kim @ 2015-04-19  3:42 UTC (permalink / raw)
  To: Taewoong Song; +Cc: Arnaldo Carvalho de Melo, linux-kernel, jolsa

On Sat, Apr 18, 2015 at 02:02:17PM +0900, Taewoong Song wrote:
> > On Apr 13, 2015, at 3:55 PM, Namhyung Kim <namhyung@kernel.org> wrote:
> > On Sun, Apr 12, 2015 at 11:44:49PM +0900, Taeung Song wrote:
> >> +static struct config_section *find_config_section(const char *section_name)
> >> +{
> >> +	struct config_section *section_node;
> > 
> > It'd be better to split declaration and function body with a blank line.
> > 
> 
> Does mean it like followed by ?
> 
> +static struct config_section *find_config_section(const char *section_name)
> +
> +{
> +	struct config_section *section_node;
> 
> ,or is it ?  
> 
> +static struct config_section *find_config_section(const char *section_name)
> +{
> +
> +	struct config_section *section_node;

Nope!  I meant

static struct config_section *find_config_section(const char *section_name)
{
	struct config_section *section node
								<-- here
	list_for_each_entry(section_node, &sections, list)
		...
}


> 
> > 
> >> +	list_for_each_entry(section_node, &sections, list)
> >> +		if (!strcmp(section_node->name, section_name))
> >> +			return section_node;
> >> +
> >> +	return NULL;
> >> +}
> >> +
> >> +static struct config_element *find_config_element(const char *subkey
> >> +						  , struct config_section *section_node)

And this is not how we put comma, please change it to

static struct config_element *find_config_element(const char *subkey,
						  struct config_section *section_node)

Ditto for others..

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/2] perf tools: Add 'perf-config' command
  2015-04-09 14:26 Taeung Song
  2015-04-09 15:57 ` Arnaldo Carvalho de Melo
@ 2015-04-10  8:53 ` Jiri Olsa
  1 sibling, 0 replies; 12+ messages in thread
From: Jiri Olsa @ 2015-04-10  8:53 UTC (permalink / raw)
  To: Taeung Song
  Cc: Arnaldo Carvalho de Melo, linux-kernel, namhyung, linux-perf-users

On Thu, Apr 09, 2015 at 11:26:30PM +0900, Taeung Song wrote:
> The perf configuration file contain many variables which can make
> the perf command's action more effective and more skilful.
> But looking through state of configuration is difficult and
> there's no knowing what kind of other variables except variables in perfconfig.example exist.
> So This patch adds 'perf-config' command with '--all' option and a document for it.

hi,
any chance the 'perf config -a' would display current config PLUS
all possible keys with their default values?  Like total overview
of the config options.. I mean all the options you described in
the doc.

While 'perf config' would display only those options you have
defined in the config file..

It could be part as next patch of course as it might need
more coding.

one nit below

thanks,
jirka

> 
> Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
> ---
>  tools/perf/Build                            |   1 +
>  tools/perf/Documentation/perf-config.txt    | 433 ++++++++++++++++++++++++++++
>  tools/perf/Documentation/perfconfig.example |  65 ++++-
>  tools/perf/builtin-config.c                 |  68 +++++

SNIP

> +	return 0;
> +}
> +
> +int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
> +{
> +	int ret = 0;
> +
> +	argc = parse_options(argc, argv, config_options, config_usage,
> +			     PARSE_OPT_STOP_AT_NON_OPTION);
> +	if (argc > 0) {
> +		if (strcmp(argv[0], "-") == 0) {
> +			pr_warning("  Error: '-' is not supported.\n");
> +			usage_with_options(config_usage, config_options);
> +		}
> +	}

for some reason you display error only for '-', and not for unknow argument

[jolsa@krava perf]$ ./perf config -
  Error: '-' is not supported.

 usage: perf config [options]

Action
    -a, --all             print all configurations

[jolsa@krava perf]$ ./perf config krava
[jolsa@krava perf]$ 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/2] perf tools: Add 'perf-config' command
  2015-04-09 14:26 Taeung Song
@ 2015-04-09 15:57 ` Arnaldo Carvalho de Melo
  2015-04-10  8:53 ` Jiri Olsa
  1 sibling, 0 replies; 12+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-04-09 15:57 UTC (permalink / raw)
  To: Taeung Song; +Cc: linux-kernel, jolsa, namhyung, linux-perf-users

Em Thu, Apr 09, 2015 at 11:26:30PM +0900, Taeung Song escreveu:
> The perf configuration file contain many variables which can make
> the perf command's action more effective and more skilful.
> But looking through state of configuration is difficult and
> there's no knowing what kind of other variables except variables in perfconfig.example exist.
> So This patch adds 'perf-config' command with '--all' option and a document for it.

Thanks for doing this! Now we need to read it thru, but having more
documentation like this is really nice!

- Arnaldo
 
> Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
> ---
>  tools/perf/Build                            |   1 +
>  tools/perf/Documentation/perf-config.txt    | 433 ++++++++++++++++++++++++++++
>  tools/perf/Documentation/perfconfig.example |  65 ++++-
>  tools/perf/builtin-config.c                 |  68 +++++
>  tools/perf/builtin.h                        |   1 +
>  tools/perf/command-list.txt                 |   1 +
>  tools/perf/perf.c                           |   1 +
>  7 files changed, 559 insertions(+), 11 deletions(-)
>  create mode 100644 tools/perf/Documentation/perf-config.txt
>  create mode 100644 tools/perf/builtin-config.c
> 
> diff --git a/tools/perf/Build b/tools/perf/Build
> index b77370e..3c1f437 100644
> --- a/tools/perf/Build
> +++ b/tools/perf/Build
> @@ -1,5 +1,6 @@
>  perf-y += builtin-bench.o
>  perf-y += builtin-annotate.o
> +perf-y += builtin-config.o
>  perf-y += builtin-diff.o
>  perf-y += builtin-evlist.o
>  perf-y += builtin-help.o
> diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
> new file mode 100644
> index 0000000..b251702
> --- /dev/null
> +++ b/tools/perf/Documentation/perf-config.txt
> @@ -0,0 +1,433 @@
> +perf-config(1)
> +==============
> +
> +NAME
> +----
> +perf-config - Get and set variables in configuration file.
> +
> +SYNOPSIS
> +--------
> +[verse]
> +'perf config' -a | --all
> +
> +DESCRIPTION
> +-----------
> +You can manage variables in configuration file with this command.
> +
> +OPTIONS
> +-------
> +
> +-a::
> +--all::
> +	Show all variables with key and value into each sections.
> +
> +CONFIGURATION FILE
> +------------------
> +
> +The Perf configuration file contain many variables which can make
> +the perf command's action more effective, more skilful.
> +The '$HOME/.perfconfig' file is used to store a per-user configuration.
> +The file 'etc/perfconfig' or '$(sysconfdir)/perfconfig' can be used to
> +store a system-wide default configuration.
> +
> +The variables are divided into sections. In each sections, the variables
> +can contain a key and values.
> +
> +Syntax
> +~~~~~~
> +
> +The file consists of sections and subkeys. A section begins with
> +the name of the section in square brackets and continues until the next
> +section begins. Each variable have to belong to some section, which means
> +there must be a section header before the first setting of a variable, as below:
> +Each variable are in the form 'subkey = value'.
> +
> +	[section]
> +		subkey1 = value1
> +		subkey2 = value2
> +
> +Subsection names are case sensitive and can contain any characters except
> +newline (doublequote `"` and backslash have to be escaped as `\"` and `\\`,
> +respectively).  Section headers cannot span multiple
> +lines.  Variables may belong directly to a section or to a given subsection.
> +
> +Example
> +~~~~~~~
> +
> +Given a $HOME/.perfconfig like this:
> +
> +#
> +# This is the config file, and
> +# a '#' and ';' character indicates a comment
> +#
> +
> +[colors]
> +	# Color variables
> +	top = red, default
> +	medium = green, default
> +	normal = lightgray, default
> +	selected = white, lightgray
> +	code = blue, default
> +	addr = magenta, default
> +	root = white, blue
> +
> +[tui]
> +	# Defaults if linked with libslang
> +	report = on
> +	annotate = on
> +	top = on
> +
> +[buildid]
> +	# Default, disable using /dev/null
> +	dir = /root/.debug
> +
> +[annotate]
> +	# Defaults
> +	hide_src_code = false
> +	use_offset = true
> +	jump_arrows = true
> +	show_nr_jumps = false
> +
> +[help]
> +	# Format can be man, info, web or html
> +	format = man
> +	autocorrect = 0
> +
> +[ui]
> +	show-headers= true
> +
> +[call-graph]
> +	# fp (framepointer), dwarf
> +	record-mode = fp
> +	print-type = graph
> +	order = caller
> +	sort-key = function
> +
> +Variables
> +~~~~~~~~~
> +
> +colors.*::
> +	Color variables can appoint colors of the output which is printed out
> +	from ‘report’, ‘top’,’annotate’ on tui.
> +	Color variables is composed of foreground and background
> +	and should have two values for them. If you want to set as colors
> +	of your terminal, you should use ‘default’ for color value.
> +        The kind of color which can be used as below.
> +	red, green, default, black, blue, white, magenta, lightgray
> +
> +	colors.top::
> +		‘top’ means a overhead percentage which has more than 5%.
> +		And values of it’s variable specify colors of percentage.
> +		Basic key values are foreground-color ’red’ and
> +		background-color ’default’.
> +	colors.medium::
> +		‘medium’ means a overhead percentage which has more than 0.5%.
> +		Default values are ’green’ and ’default’.
> +	colors.normal::
> +		‘normal’ means rest of overhead percentages
> +		except ‘top’, ‘medium’, ‘selected’.
> +		Default values are ’lightgray’ and ’default’.
> +	colors.selected::
> +		This appoint colors for forcussed one of the output list
> +		from sub-commands (top,report,annotate).
> +		Default values are ’white’ and ’lightgray’.
> +	colors.code::
> +		Colors for a arrow and lines on jumping by assembly code
> +		such as ‘jns’,’jmp’,’jane’,etc. Default values are ‘blue’, ‘default’.
> +	colors.addr::
> +		This appoint colors for addresses from a sub-command ’annotate’.
> +		Default values are ‘magenta’, ‘default’.
> +	colors.root::
> +		Colors for headers in the output of a sub-command ‘top’.
> +		Default values are ‘white’, ‘blue’.
> +
> +tui.*::
> +	A boolean value that controls launching TUI browser for each subcommand.
> +	By default, TUI is enabled if perf detects a needed library during build
> +	and this config option can control it.  Available subcommands are 'top',
> +	'report' and 'annotate'.
> +
> +gtk.*::
> +	A boolean value that controls launching GTK+2 GUI browser for
> +	each subcommand.  By default, TUI is enabled if perf detects a
> +	needed library during build and this config option can control
> +	it.  Available subcommands are 'top', 'report' and 'annotate'.
> +
> +buildid.*::
> +	buildid.dir::
> +		Each executable or shared library built with each program is assigned
> +		a unique identification as build-id. The option means a path where
> +		build-id information can be saved.
> +		The default is $HOME/.debug
> +
> +annotate.*::
> +	There’re options which work with a ’annotate’ sub-command.
> +	This Options is in control of addresses, jump function, source code
> +	in lines of assembly code from a specific program.
> +
> +	annotate.hide_src_code::
> +		If a program which is analyzed has source code of itself,
> +		this option let ‘annotate’ print a list of assembly code with the source code.
> +		For example, let’s see a part of a program. There’re four lines.
> +		If this option is ‘false’, they can be printed
> +		without source code from a program as below.
> +
> +		│        push   %rbp
> +		│        mov    %rsp,%rbp
> +		│        sub    $0x10,%rsp
> +		│        mov    (%rdi),%rdx
> +
> +		But if this option is ‘true’, source code of the part
> +		can be also printed as below.
> +
> +		│      struct rb_node *rb_next(const struct rb_node *node)
> +		│      {
> +		│        push   %rbp
> +		│        mov    %rsp,%rbp
> +		│        sub    $0x10,%rsp
> +		│              struct rb_node *parent;
> +		│
> +		│              if (RB_EMPTY_NODE(node))
> +		│        mov    (%rdi),%rdx
> +		│              return n;
> +
> +        annotate.use_offset::
> +		Basing on a first address of a loaded function, offset can be used.
> +		Instead of using original addresses of assembly code,
> +		addresses subtracted from a base address can be printed.
> +		Let’s illustrate a example.
> +		If a base address is 0XFFFFFFFF81624d50 as below,
> +
> +		ffffffff81624d50 <load0>
> +
> +		a address on assembly code has a specific absolute address as below
> +
> +		ffffffff816250b8:│  mov    0x8(%r14),%rdi
> +
> +		but if use_offset is ’true’, a address subtracted from a base address is printed.
> +		The default is true.
> +
> +		             368:│  mov    0x8(%r14),%rdi
> +
> +	annotate.jump_arrows::
> +		There’re jump instruction among assembly code.
> +		Depending on a boolean value of jump_arrows,
> +		arrows can be printed or not which represent
> +		where do the instruction jump into as below.
> +
> +		│     ┌──jmp    1333
> +		│     │  xchg   %ax,%ax
> +		│1330:│  mov    %r15,%r10
> +		│1333:└─→cmp    %r15,%r14
> +
> +		If jump_arrow is ‘false’, the arrows isn’t printed as below.
> +
> +		│      ↓ jmp    1333
> +		│        xchg   %ax,%ax
> +		│1330:   mov    %r15,%r10
> +		│1333:   cmp    %r15,%r14
> +
> +        annotate.show_nr_jumps::
> +		Let’s see a part of assembly code.
> +
> +		│1382:   movb   $0x1,-0x270(%rbp)
> +
> +		If use this, the number of branches branching to that address can be printed as below.
> +
> +		│1 1382:   movb   $0x1,-0x270(%rbp)
> +
> +help.*::
> +	help.format:: = man
> +		A format of manual page can be ‘man’, ‘info’, ‘web’ or ‘html’.
> +		’man’ is default.
> +	help.autocorrect:: = 0
> +		Automatically correct and execute mistyped commands after
> +		waiting for the given number of deciseconds (0.1 sec).
> +		Let's see a example. If a mistyped sub-command is executed like 'perf mistyped-command'
> +		and this option is 0, the output is as below.
> +
> +		perf: 'mistyped-command' is not a perf-command. See 'perf --help’.
> +
> +		Or if this option is more than 1, the output can be such as.
> +
> +		WARNING: You called a perf program named 'mistyped-command', which does not exist.
> +		Continuing under the assumption that you meant 'with-kcore'
> +		in 0.1 seconds automatically...
> +		Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]
> +		<perf sub-command> can be record, script, report or inject
> +		    or: perf-with-kcore fix_buildid_cache_permissions
> +
> +hist.*::
> +	hist.percentage::
> +		This option control a way to calcurate overhead of filtered entries -
> +		that means the value of this option is effective only if there's a
> +		filter (by comm, dso or symbol name).  Suppose a following example:
> +
> +		       Overhead  Symbols
> +		       ........  .......
> +		        33.33%     foo
> +		        33.33%     bar
> +		        33.33%     baz
> +
> +	       This is an original overhead and we'll filter out the first 'foo'
> +	       entry.  The value of 'relative' would increase the overhead of 'bar'
> +	       and 'baz' to 50.00% for each, while 'absolute' would show their
> +	       current overhead (33.33%).
> +
> +ui.*::
> +	ui.show-headers::
> +		There’re columns as header ‘Overhead’, ‘Children’, ‘Shared Object’, ‘Symbol’, ’self’.
> +		If this option is false, they are hiden.
> +
> +call-graph.*::
> +	When sub-commands ‘top’ and ‘report’ work with -g/—-children
> +	there’re options in control of call-graph.
> +
> +	call-graph.record-mode::
> +		The record-mode can be ‘fp’ (frame pointer) and ‘dwarf’.
> +		The value of 'dwarf' is effective only if perf detect needed library
> +		(libunwind or a recent version of libdw).  Also it doesn't *require*
> +		the dump-size option since it can use the default value of 8192 if
> +		missing.
> +
> +	call-graph.dump-size::
> +		The size of stack to dump in order to do post-unwinding.  Default is 8192 (byte).
> +		When using dwarf into record-mode this option should have a value.
> +
> +	call-graph.print-type::
> +		The print-types can be graph (graph absolute), fractal (graph relative), flat.
> +		This option controls a way to show overhead for each callchain entry.
> +		Suppose a following example.
> +
> +		Overhead  Symbols
> +		........  .......
> +		  40.00%  foo
> +		      |
> +		      --- foo
> +		      |
> +		      |--50.00%-- bar
> +		      |           main
> +		      |
> +		      --50.00%-- baz
> +		                 main
> +
> +		This output is a default format which is 'fractal'.  The 'foo' came
> +		from 'bar' and 'baz' exactly half and half so 'fractal' shows 50.00%
> +		for each (meaning that it assumes 100% total overhead of 'foo').
> +
> +		The 'graph' uses absolute overhead value of 'foo' as total so each of
> +		'bar' and 'baz' callchain will have 20.00% of overhead.
> +
> +	call-graph.order::
> +		This option controls print order of callchains.  The default is
> +		'callee' which means callee is printed at top and then followed by its
> +		caller and so on.  The 'caller' prints it in reverse order.
> +
> +	call-graph.sort-key::
> +		The callchains are merged if they contain same information.
> +		The sort-key option determines a way to compare the callchains.
> +		A value of 'sort-key' can be 'function' or 'address’.
> +		The default is ‘function’.
> +
> +	call-graph.threshold::
> +		When there're many callchains it'd print tons of lines.  So perf omits
> +		small callchains under a certain overhead (threshold) and this option
> +		control the threashold.  Default is 0.5 (%).
> +
> +	call-graph.print-limit::
> +		This is another way to control the number of callchains printed for a
> +		single entry.  Default is 0 which means no limitation.
> +
> +report.*::
> +	report.percent-limit::
> +		This one is mostly same as call-graph.threshold but works for
> +		histogram entries.  Entries have overhead lower than this percentage
> +		will not be printed.  Default is 0.
> +		If percent-limit is 70, the output which has percentages of
> +		each overhead above 70% can be printed.
> +
> +	report.queue-size::
> +		option to setup the maximum allocation size for session's
> +		ordered events queue, if not set there's no default limit
> +
> +	report.children::
> +		The children means that functions called from another function.
> +		If the option is true, accumulate callchain of children and show total overhead.
> +		For example, there’re three functions like below.
> +
> +		 void foo(void) {
> +		   /* do something */
> +		 }
> +
> +		 void bar(void) {
> +		   /* do something */
> +		   foo();
> +		 }
> +
> +		 int main(void) {
> +		   bar()
> +		   return 0;
> +		 }
> +
> +		Defaultly the output of sub-commands such as ’top’, ‘report’ and ‘annotate’
> +		depend on a sort of overhead into each functions as below.
> +
> +		Overhead  Symbol
> +		........  .....................
> +		  60.00%  foo
> +		          |
> +		          --- foo
> +		              bar
> +		              main
> +		              __libc_start_main
> +
> +		  40.00%  bar
> +		          |
> +		          --- bar
> +		              main
> +		              __libc_start_main
> +
> +		But if this option is true, the sort is changed into a sort of
> +		overhead into each children group of each function  reciting all functions
> +		from a first parent function till a last child function like below.
> +		And it requires -g/--call-graph option enabled
> +
> +		Children      Self  Symbol
> +		........  ........  ....................
> +		 100.00%     0.00%  __libc_start_main
> +		          |
> +		          --- __libc_start_main
> +
> +		 100.00%     0.00%  main
> +		          |
> +		          --- main
> +		              __libc_start_main
> +
> +		 100.00%    40.00%  bar
> +		          |
> +		          --- bar
> +		              main
> +		              __libc_start_main
> +
> +		  60.00%    60.00%  foo
> +		          |
> +		          --- foo
> +		              bar
> +		              main
> +		              __libc_start_main
> +
> +top.*::
> +	top.children::
> +		This option means same as report.children.
> +		So it is true, the output of ‘top’ is rearranged by each overhead into children group.
> +
> +man.*::
> +	man.viewer::
> +
> +pager.*::
> +	pager.report::
> +	pager
> +
> +SEE ALSO
> +--------
> +linkperf:perf[1]
> diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
> index 767ea24..853aa20 100644
> --- a/tools/perf/Documentation/perfconfig.example
> +++ b/tools/perf/Documentation/perfconfig.example
> @@ -1,29 +1,72 @@
>  [colors]
> -
> -	# These were the old defaults
> -	top = red, lightgray
> -	medium = green, lightgray
> -	normal = black, lightgray
> -	selected = lightgray, magenta
> -	code = blue, lightgray
> -	addr = magenta, lightgray
> +	# There are types of colors which are red,
> +	# green, default, black, blue,
> +	# white, magenta, lightgray
> +	# The default is like below
> +	top = red, default
> +	medium = green, default
> +	normal = lightgray, default
> +	selected = white, lightgray
> +	code = blue, default
> +	addr = magenta, default
> +	root = white, blue
>  
>  [tui]
> -
>  	# Defaults if linked with libslang
>  	report = on
>  	annotate = on
>  	top = on
>  
>  [buildid]
> -
>  	# Default, disable using /dev/null
>  	dir = /root/.debug
>  
>  [annotate]
> -
>  	# Defaults
>  	hide_src_code = false
>  	use_offset = true
>  	jump_arrows = true
>  	show_nr_jumps = false
> +
> +[gtk]
> +	report = off
> +	annotate = off
> +	#top = off
> +
> +[pager]
> +	# That a 'cmd' is true mean to use "pager or less"
> +	cmd = true
> +	report = false
> +	diff = true
> +
> +[help]
> +	# Format can be man, info, web or html
> +	format = man
> +	autocorrect = 0
> +
> +[hist]
> +	# a value of 'percentage' can be 'relative' or 'absolute'
> +	percentage = absolute
> +
> +[ui]
> +	show-headers= true
> +
> +[call-graph]
> +	# fp (framepointer), dwarf
> +	record-mode = fp
> +
> +	# graph (graph absolute), flat, fractal (graph relative)
> +	print-type = fractal
> +
> +	# caller, callee
> +	order = caller
> +
> +	# function, address
> +	sort-key = function
> +
> +[report]
> +	percent-limit = 1
> +	children = false
> +
> +[top]
> +	children = true
> diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
> new file mode 100644
> index 0000000..32f8ae6
> --- /dev/null
> +++ b/tools/perf/builtin-config.c
> @@ -0,0 +1,68 @@
> +/*
> + * builtin-config.c
> + *
> + * Copyright (C) 2015, Taeung Song <treeze.taeung@gmail.com>
> + *
> + */
> +#include "builtin.h"
> +
> +#include "perf.h"
> +
> +#include "util/cache.h"
> +#include "util/parse-options.h"
> +#include "util/util.h"
> +#include "util/debug.h"
> +
> +static struct {
> +	bool all_action;
> +} params;
> +
> +static const char * const config_usage[] = {
> +	"perf config [options]",
> +	NULL
> +};
> +static const struct option config_options[] = {
> +	OPT_GROUP("Action"),
> +	OPT_BOOLEAN('a', "all", &params.all_action, "print all configurations"),
> +	OPT_END()
> +};
> +
> +static void check_argc(int argc, int limit)
> +{
> +	if (argc >= limit && argc <= limit)
> +		return;
> +	error("wrong number of arguments");
> +	usage_with_options(config_usage, config_options);
> +}
> +
> +static int show_config(const char *key, const char *value,
> +			   void *cb __maybe_unused)
> +{
> +	if (value)
> +		printf("%s=%s\n", key, value);
> +	else
> +		printf("%s\n", key);
> +
> +	return 0;
> +}
> +
> +int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
> +{
> +	int ret = 0;
> +
> +	argc = parse_options(argc, argv, config_options, config_usage,
> +			     PARSE_OPT_STOP_AT_NON_OPTION);
> +	if (argc > 0) {
> +		if (strcmp(argv[0], "-") == 0) {
> +			pr_warning("  Error: '-' is not supported.\n");
> +			usage_with_options(config_usage, config_options);
> +		}
> +	}
> +
> +	if (argc == 0 || params.all_action) {
> +		check_argc(argc, 0);
> +		ret = perf_config(show_config, NULL);
> +	}
> +
> +	return ret;
> +}
> diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
> index 3688ad2..3f871b5 100644
> --- a/tools/perf/builtin.h
> +++ b/tools/perf/builtin.h
> @@ -17,6 +17,7 @@ extern int cmd_annotate(int argc, const char **argv, const char *prefix);
>  extern int cmd_bench(int argc, const char **argv, const char *prefix);
>  extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix);
>  extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
> +extern int cmd_config(int argc, const char **argv, const char *prefix);
>  extern int cmd_diff(int argc, const char **argv, const char *prefix);
>  extern int cmd_evlist(int argc, const char **argv, const char *prefix);
>  extern int cmd_help(int argc, const char **argv, const char *prefix);
> diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
> index 00fcaf8..acc3ea7 100644
> --- a/tools/perf/command-list.txt
> +++ b/tools/perf/command-list.txt
> @@ -9,6 +9,7 @@ perf-buildid-cache		mainporcelain common
>  perf-buildid-list		mainporcelain common
>  perf-data			mainporcelain common
>  perf-diff			mainporcelain common
> +perf-config			mainporcelain common
>  perf-evlist			mainporcelain common
>  perf-inject			mainporcelain common
>  perf-kmem			mainporcelain common
> diff --git a/tools/perf/perf.c b/tools/perf/perf.c
> index b857fcb..604fa4a 100644
> --- a/tools/perf/perf.c
> +++ b/tools/perf/perf.c
> @@ -37,6 +37,7 @@ struct cmd_struct {
>  static struct cmd_struct commands[] = {
>  	{ "buildid-cache", cmd_buildid_cache, 0 },
>  	{ "buildid-list", cmd_buildid_list, 0 },
> +	{ "config",	cmd_config,	0 },
>  	{ "diff",	cmd_diff,	0 },
>  	{ "evlist",	cmd_evlist,	0 },
>  	{ "help",	cmd_help,	0 },
> -- 
> 1.9.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/2] perf tools: Add 'perf-config' command
@ 2015-04-09 14:26 Taeung Song
  2015-04-09 15:57 ` Arnaldo Carvalho de Melo
  2015-04-10  8:53 ` Jiri Olsa
  0 siblings, 2 replies; 12+ messages in thread
From: Taeung Song @ 2015-04-09 14:26 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, jolsa, namhyung, linux-perf-users, Taeung Song

The perf configuration file contain many variables which can make
the perf command's action more effective and more skilful.
But looking through state of configuration is difficult and
there's no knowing what kind of other variables except variables in perfconfig.example exist.
So This patch adds 'perf-config' command with '--all' option and a document for it.

Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
 tools/perf/Build                            |   1 +
 tools/perf/Documentation/perf-config.txt    | 433 ++++++++++++++++++++++++++++
 tools/perf/Documentation/perfconfig.example |  65 ++++-
 tools/perf/builtin-config.c                 |  68 +++++
 tools/perf/builtin.h                        |   1 +
 tools/perf/command-list.txt                 |   1 +
 tools/perf/perf.c                           |   1 +
 7 files changed, 559 insertions(+), 11 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-config.txt
 create mode 100644 tools/perf/builtin-config.c

diff --git a/tools/perf/Build b/tools/perf/Build
index b77370e..3c1f437 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -1,5 +1,6 @@
 perf-y += builtin-bench.o
 perf-y += builtin-annotate.o
+perf-y += builtin-config.o
 perf-y += builtin-diff.o
 perf-y += builtin-evlist.o
 perf-y += builtin-help.o
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
new file mode 100644
index 0000000..b251702
--- /dev/null
+++ b/tools/perf/Documentation/perf-config.txt
@@ -0,0 +1,433 @@
+perf-config(1)
+==============
+
+NAME
+----
+perf-config - Get and set variables in configuration file.
+
+SYNOPSIS
+--------
+[verse]
+'perf config' -a | --all
+
+DESCRIPTION
+-----------
+You can manage variables in configuration file with this command.
+
+OPTIONS
+-------
+
+-a::
+--all::
+	Show all variables with key and value into each sections.
+
+CONFIGURATION FILE
+------------------
+
+The Perf configuration file contain many variables which can make
+the perf command's action more effective, more skilful.
+The '$HOME/.perfconfig' file is used to store a per-user configuration.
+The file 'etc/perfconfig' or '$(sysconfdir)/perfconfig' can be used to
+store a system-wide default configuration.
+
+The variables are divided into sections. In each sections, the variables
+can contain a key and values.
+
+Syntax
+~~~~~~
+
+The file consists of sections and subkeys. A section begins with
+the name of the section in square brackets and continues until the next
+section begins. Each variable have to belong to some section, which means
+there must be a section header before the first setting of a variable, as below:
+Each variable are in the form 'subkey = value'.
+
+	[section]
+		subkey1 = value1
+		subkey2 = value2
+
+Subsection names are case sensitive and can contain any characters except
+newline (doublequote `"` and backslash have to be escaped as `\"` and `\\`,
+respectively).  Section headers cannot span multiple
+lines.  Variables may belong directly to a section or to a given subsection.
+
+Example
+~~~~~~~
+
+Given a $HOME/.perfconfig like this:
+
+#
+# This is the config file, and
+# a '#' and ';' character indicates a comment
+#
+
+[colors]
+	# Color variables
+	top = red, default
+	medium = green, default
+	normal = lightgray, default
+	selected = white, lightgray
+	code = blue, default
+	addr = magenta, default
+	root = white, blue
+
+[tui]
+	# Defaults if linked with libslang
+	report = on
+	annotate = on
+	top = on
+
+[buildid]
+	# Default, disable using /dev/null
+	dir = /root/.debug
+
+[annotate]
+	# Defaults
+	hide_src_code = false
+	use_offset = true
+	jump_arrows = true
+	show_nr_jumps = false
+
+[help]
+	# Format can be man, info, web or html
+	format = man
+	autocorrect = 0
+
+[ui]
+	show-headers= true
+
+[call-graph]
+	# fp (framepointer), dwarf
+	record-mode = fp
+	print-type = graph
+	order = caller
+	sort-key = function
+
+Variables
+~~~~~~~~~
+
+colors.*::
+	Color variables can appoint colors of the output which is printed out
+	from ‘report’, ‘top’,’annotate’ on tui.
+	Color variables is composed of foreground and background
+	and should have two values for them. If you want to set as colors
+	of your terminal, you should use ‘default’ for color value.
+        The kind of color which can be used as below.
+	red, green, default, black, blue, white, magenta, lightgray
+
+	colors.top::
+		‘top’ means a overhead percentage which has more than 5%.
+		And values of it’s variable specify colors of percentage.
+		Basic key values are foreground-color ’red’ and
+		background-color ’default’.
+	colors.medium::
+		‘medium’ means a overhead percentage which has more than 0.5%.
+		Default values are ’green’ and ’default’.
+	colors.normal::
+		‘normal’ means rest of overhead percentages
+		except ‘top’, ‘medium’, ‘selected’.
+		Default values are ’lightgray’ and ’default’.
+	colors.selected::
+		This appoint colors for forcussed one of the output list
+		from sub-commands (top,report,annotate).
+		Default values are ’white’ and ’lightgray’.
+	colors.code::
+		Colors for a arrow and lines on jumping by assembly code
+		such as ‘jns’,’jmp’,’jane’,etc. Default values are ‘blue’, ‘default’.
+	colors.addr::
+		This appoint colors for addresses from a sub-command ’annotate’.
+		Default values are ‘magenta’, ‘default’.
+	colors.root::
+		Colors for headers in the output of a sub-command ‘top’.
+		Default values are ‘white’, ‘blue’.
+
+tui.*::
+	A boolean value that controls launching TUI browser for each subcommand.
+	By default, TUI is enabled if perf detects a needed library during build
+	and this config option can control it.  Available subcommands are 'top',
+	'report' and 'annotate'.
+
+gtk.*::
+	A boolean value that controls launching GTK+2 GUI browser for
+	each subcommand.  By default, TUI is enabled if perf detects a
+	needed library during build and this config option can control
+	it.  Available subcommands are 'top', 'report' and 'annotate'.
+
+buildid.*::
+	buildid.dir::
+		Each executable or shared library built with each program is assigned
+		a unique identification as build-id. The option means a path where
+		build-id information can be saved.
+		The default is $HOME/.debug
+
+annotate.*::
+	There’re options which work with a ’annotate’ sub-command.
+	This Options is in control of addresses, jump function, source code
+	in lines of assembly code from a specific program.
+
+	annotate.hide_src_code::
+		If a program which is analyzed has source code of itself,
+		this option let ‘annotate’ print a list of assembly code with the source code.
+		For example, let’s see a part of a program. There’re four lines.
+		If this option is ‘false’, they can be printed
+		without source code from a program as below.
+
+		│        push   %rbp
+		│        mov    %rsp,%rbp
+		│        sub    $0x10,%rsp
+		│        mov    (%rdi),%rdx
+
+		But if this option is ‘true’, source code of the part
+		can be also printed as below.
+
+		│      struct rb_node *rb_next(const struct rb_node *node)
+		│      {
+		│        push   %rbp
+		│        mov    %rsp,%rbp
+		│        sub    $0x10,%rsp
+		│              struct rb_node *parent;
+		│
+		│              if (RB_EMPTY_NODE(node))
+		│        mov    (%rdi),%rdx
+		│              return n;
+
+        annotate.use_offset::
+		Basing on a first address of a loaded function, offset can be used.
+		Instead of using original addresses of assembly code,
+		addresses subtracted from a base address can be printed.
+		Let’s illustrate a example.
+		If a base address is 0XFFFFFFFF81624d50 as below,
+
+		ffffffff81624d50 <load0>
+
+		a address on assembly code has a specific absolute address as below
+
+		ffffffff816250b8:│  mov    0x8(%r14),%rdi
+
+		but if use_offset is ’true’, a address subtracted from a base address is printed.
+		The default is true.
+
+		             368:│  mov    0x8(%r14),%rdi
+
+	annotate.jump_arrows::
+		There’re jump instruction among assembly code.
+		Depending on a boolean value of jump_arrows,
+		arrows can be printed or not which represent
+		where do the instruction jump into as below.
+
+		│     ┌──jmp    1333
+		│     │  xchg   %ax,%ax
+		│1330:│  mov    %r15,%r10
+		│1333:└─→cmp    %r15,%r14
+
+		If jump_arrow is ‘false’, the arrows isn’t printed as below.
+
+		│      ↓ jmp    1333
+		│        xchg   %ax,%ax
+		│1330:   mov    %r15,%r10
+		│1333:   cmp    %r15,%r14
+
+        annotate.show_nr_jumps::
+		Let’s see a part of assembly code.
+
+		│1382:   movb   $0x1,-0x270(%rbp)
+
+		If use this, the number of branches branching to that address can be printed as below.
+
+		│1 1382:   movb   $0x1,-0x270(%rbp)
+
+help.*::
+	help.format:: = man
+		A format of manual page can be ‘man’, ‘info’, ‘web’ or ‘html’.
+		’man’ is default.
+	help.autocorrect:: = 0
+		Automatically correct and execute mistyped commands after
+		waiting for the given number of deciseconds (0.1 sec).
+		Let's see a example. If a mistyped sub-command is executed like 'perf mistyped-command'
+		and this option is 0, the output is as below.
+
+		perf: 'mistyped-command' is not a perf-command. See 'perf --help’.
+
+		Or if this option is more than 1, the output can be such as.
+
+		WARNING: You called a perf program named 'mistyped-command', which does not exist.
+		Continuing under the assumption that you meant 'with-kcore'
+		in 0.1 seconds automatically...
+		Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]
+		<perf sub-command> can be record, script, report or inject
+		    or: perf-with-kcore fix_buildid_cache_permissions
+
+hist.*::
+	hist.percentage::
+		This option control a way to calcurate overhead of filtered entries -
+		that means the value of this option is effective only if there's a
+		filter (by comm, dso or symbol name).  Suppose a following example:
+
+		       Overhead  Symbols
+		       ........  .......
+		        33.33%     foo
+		        33.33%     bar
+		        33.33%     baz
+
+	       This is an original overhead and we'll filter out the first 'foo'
+	       entry.  The value of 'relative' would increase the overhead of 'bar'
+	       and 'baz' to 50.00% for each, while 'absolute' would show their
+	       current overhead (33.33%).
+
+ui.*::
+	ui.show-headers::
+		There’re columns as header ‘Overhead’, ‘Children’, ‘Shared Object’, ‘Symbol’, ’self’.
+		If this option is false, they are hiden.
+
+call-graph.*::
+	When sub-commands ‘top’ and ‘report’ work with -g/—-children
+	there’re options in control of call-graph.
+
+	call-graph.record-mode::
+		The record-mode can be ‘fp’ (frame pointer) and ‘dwarf’.
+		The value of 'dwarf' is effective only if perf detect needed library
+		(libunwind or a recent version of libdw).  Also it doesn't *require*
+		the dump-size option since it can use the default value of 8192 if
+		missing.
+
+	call-graph.dump-size::
+		The size of stack to dump in order to do post-unwinding.  Default is 8192 (byte).
+		When using dwarf into record-mode this option should have a value.
+
+	call-graph.print-type::
+		The print-types can be graph (graph absolute), fractal (graph relative), flat.
+		This option controls a way to show overhead for each callchain entry.
+		Suppose a following example.
+
+		Overhead  Symbols
+		........  .......
+		  40.00%  foo
+		      |
+		      --- foo
+		      |
+		      |--50.00%-- bar
+		      |           main
+		      |
+		      --50.00%-- baz
+		                 main
+
+		This output is a default format which is 'fractal'.  The 'foo' came
+		from 'bar' and 'baz' exactly half and half so 'fractal' shows 50.00%
+		for each (meaning that it assumes 100% total overhead of 'foo').
+
+		The 'graph' uses absolute overhead value of 'foo' as total so each of
+		'bar' and 'baz' callchain will have 20.00% of overhead.
+
+	call-graph.order::
+		This option controls print order of callchains.  The default is
+		'callee' which means callee is printed at top and then followed by its
+		caller and so on.  The 'caller' prints it in reverse order.
+
+	call-graph.sort-key::
+		The callchains are merged if they contain same information.
+		The sort-key option determines a way to compare the callchains.
+		A value of 'sort-key' can be 'function' or 'address’.
+		The default is ‘function’.
+
+	call-graph.threshold::
+		When there're many callchains it'd print tons of lines.  So perf omits
+		small callchains under a certain overhead (threshold) and this option
+		control the threashold.  Default is 0.5 (%).
+
+	call-graph.print-limit::
+		This is another way to control the number of callchains printed for a
+		single entry.  Default is 0 which means no limitation.
+
+report.*::
+	report.percent-limit::
+		This one is mostly same as call-graph.threshold but works for
+		histogram entries.  Entries have overhead lower than this percentage
+		will not be printed.  Default is 0.
+		If percent-limit is 70, the output which has percentages of
+		each overhead above 70% can be printed.
+
+	report.queue-size::
+		option to setup the maximum allocation size for session's
+		ordered events queue, if not set there's no default limit
+
+	report.children::
+		The children means that functions called from another function.
+		If the option is true, accumulate callchain of children and show total overhead.
+		For example, there’re three functions like below.
+
+		 void foo(void) {
+		   /* do something */
+		 }
+
+		 void bar(void) {
+		   /* do something */
+		   foo();
+		 }
+
+		 int main(void) {
+		   bar()
+		   return 0;
+		 }
+
+		Defaultly the output of sub-commands such as ’top’, ‘report’ and ‘annotate’
+		depend on a sort of overhead into each functions as below.
+
+		Overhead  Symbol
+		........  .....................
+		  60.00%  foo
+		          |
+		          --- foo
+		              bar
+		              main
+		              __libc_start_main
+
+		  40.00%  bar
+		          |
+		          --- bar
+		              main
+		              __libc_start_main
+
+		But if this option is true, the sort is changed into a sort of
+		overhead into each children group of each function  reciting all functions
+		from a first parent function till a last child function like below.
+		And it requires -g/--call-graph option enabled
+
+		Children      Self  Symbol
+		........  ........  ....................
+		 100.00%     0.00%  __libc_start_main
+		          |
+		          --- __libc_start_main
+
+		 100.00%     0.00%  main
+		          |
+		          --- main
+		              __libc_start_main
+
+		 100.00%    40.00%  bar
+		          |
+		          --- bar
+		              main
+		              __libc_start_main
+
+		  60.00%    60.00%  foo
+		          |
+		          --- foo
+		              bar
+		              main
+		              __libc_start_main
+
+top.*::
+	top.children::
+		This option means same as report.children.
+		So it is true, the output of ‘top’ is rearranged by each overhead into children group.
+
+man.*::
+	man.viewer::
+
+pager.*::
+	pager.report::
+	pager
+
+SEE ALSO
+--------
+linkperf:perf[1]
diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
index 767ea24..853aa20 100644
--- a/tools/perf/Documentation/perfconfig.example
+++ b/tools/perf/Documentation/perfconfig.example
@@ -1,29 +1,72 @@
 [colors]
-
-	# These were the old defaults
-	top = red, lightgray
-	medium = green, lightgray
-	normal = black, lightgray
-	selected = lightgray, magenta
-	code = blue, lightgray
-	addr = magenta, lightgray
+	# There are types of colors which are red,
+	# green, default, black, blue,
+	# white, magenta, lightgray
+	# The default is like below
+	top = red, default
+	medium = green, default
+	normal = lightgray, default
+	selected = white, lightgray
+	code = blue, default
+	addr = magenta, default
+	root = white, blue
 
 [tui]
-
 	# Defaults if linked with libslang
 	report = on
 	annotate = on
 	top = on
 
 [buildid]
-
 	# Default, disable using /dev/null
 	dir = /root/.debug
 
 [annotate]
-
 	# Defaults
 	hide_src_code = false
 	use_offset = true
 	jump_arrows = true
 	show_nr_jumps = false
+
+[gtk]
+	report = off
+	annotate = off
+	#top = off
+
+[pager]
+	# That a 'cmd' is true mean to use "pager or less"
+	cmd = true
+	report = false
+	diff = true
+
+[help]
+	# Format can be man, info, web or html
+	format = man
+	autocorrect = 0
+
+[hist]
+	# a value of 'percentage' can be 'relative' or 'absolute'
+	percentage = absolute
+
+[ui]
+	show-headers= true
+
+[call-graph]
+	# fp (framepointer), dwarf
+	record-mode = fp
+
+	# graph (graph absolute), flat, fractal (graph relative)
+	print-type = fractal
+
+	# caller, callee
+	order = caller
+
+	# function, address
+	sort-key = function
+
+[report]
+	percent-limit = 1
+	children = false
+
+[top]
+	children = true
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
new file mode 100644
index 0000000..32f8ae6
--- /dev/null
+++ b/tools/perf/builtin-config.c
@@ -0,0 +1,68 @@
+/*
+ * builtin-config.c
+ *
+ * Copyright (C) 2015, Taeung Song <treeze.taeung@gmail.com>
+ *
+ */
+#include "builtin.h"
+
+#include "perf.h"
+
+#include "util/cache.h"
+#include "util/parse-options.h"
+#include "util/util.h"
+#include "util/debug.h"
+
+static struct {
+	bool all_action;
+} params;
+
+static const char * const config_usage[] = {
+	"perf config [options]",
+	NULL
+};
+static const struct option config_options[] = {
+	OPT_GROUP("Action"),
+	OPT_BOOLEAN('a', "all", &params.all_action, "print all configurations"),
+	OPT_END()
+};
+
+static void check_argc(int argc, int limit)
+{
+	if (argc >= limit && argc <= limit)
+		return;
+	error("wrong number of arguments");
+	usage_with_options(config_usage, config_options);
+}
+
+static int show_config(const char *key, const char *value,
+			   void *cb __maybe_unused)
+{
+	if (value)
+		printf("%s=%s\n", key, value);
+	else
+		printf("%s\n", key);
+
+	return 0;
+}
+
+int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+	int ret = 0;
+
+	argc = parse_options(argc, argv, config_options, config_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+	if (argc > 0) {
+		if (strcmp(argv[0], "-") == 0) {
+			pr_warning("  Error: '-' is not supported.\n");
+			usage_with_options(config_usage, config_options);
+		}
+	}
+
+	if (argc == 0 || params.all_action) {
+		check_argc(argc, 0);
+		ret = perf_config(show_config, NULL);
+	}
+
+	return ret;
+}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 3688ad2..3f871b5 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -17,6 +17,7 @@ extern int cmd_annotate(int argc, const char **argv, const char *prefix);
 extern int cmd_bench(int argc, const char **argv, const char *prefix);
 extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix);
 extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
+extern int cmd_config(int argc, const char **argv, const char *prefix);
 extern int cmd_diff(int argc, const char **argv, const char *prefix);
 extern int cmd_evlist(int argc, const char **argv, const char *prefix);
 extern int cmd_help(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 00fcaf8..acc3ea7 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -9,6 +9,7 @@ perf-buildid-cache		mainporcelain common
 perf-buildid-list		mainporcelain common
 perf-data			mainporcelain common
 perf-diff			mainporcelain common
+perf-config			mainporcelain common
 perf-evlist			mainporcelain common
 perf-inject			mainporcelain common
 perf-kmem			mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index b857fcb..604fa4a 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -37,6 +37,7 @@ struct cmd_struct {
 static struct cmd_struct commands[] = {
 	{ "buildid-cache", cmd_buildid_cache, 0 },
 	{ "buildid-list", cmd_buildid_list, 0 },
+	{ "config",	cmd_config,	0 },
 	{ "diff",	cmd_diff,	0 },
 	{ "evlist",	cmd_evlist,	0 },
 	{ "help",	cmd_help,	0 },
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/2] perf tools: Add 'perf-config' command
  2015-04-04 17:41 Taeung Song
@ 2015-04-07 17:57 ` Jiri Olsa
  0 siblings, 0 replies; 12+ messages in thread
From: Jiri Olsa @ 2015-04-07 17:57 UTC (permalink / raw)
  To: Taeung Song; +Cc: Arnaldo Carvalho de Melo, linux-kernel, namhyung

On Sun, Apr 05, 2015 at 02:41:27AM +0900, Taeung Song wrote:

SNIP

> +	"perf config [options]",
> +	NULL
> +};
> +static const struct option config_options[] = {
> +	OPT_BOOLEAN('l', "list", &params.list_action, "list up current configurations"),
> +	OPT_END()
> +};
> +
> +static void check_argc(int argc, int min, int max)

seems like all callers have min == max, so there's no need for 2 params

jirka

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/2] perf tools: Add 'perf-config' command
@ 2015-04-04 17:41 Taeung Song
  2015-04-07 17:57 ` Jiri Olsa
  0 siblings, 1 reply; 12+ messages in thread
From: Taeung Song @ 2015-04-04 17:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: linux-kernel, jolsa, namhyung, Taeung Song

The perf configuration file contain many variables which can make
the perf command's action more effective and more skilful.
But looking through state of configuration is difficult and
there's no knowing what kind of other variables except variables in perfconfig.example exist.
So This patch adds 'perf-config' command with '--list' option and a document for it.

Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
 tools/perf/Build                            |   1 +
 tools/perf/Documentation/perf-config.txt    | 418 ++++++++++++++++++++++++++++
 tools/perf/Documentation/perfconfig.example |  65 ++++-
 tools/perf/builtin-config.c                 |  67 +++++
 tools/perf/builtin.h                        |   1 +
 tools/perf/command-list.txt                 |   1 +
 tools/perf/perf.c                           |   1 +
 7 files changed, 543 insertions(+), 11 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-config.txt
 create mode 100644 tools/perf/builtin-config.c

diff --git a/tools/perf/Build b/tools/perf/Build
index b77370e..3c1f437 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -1,5 +1,6 @@
 perf-y += builtin-bench.o
 perf-y += builtin-annotate.o
+perf-y += builtin-config.o
 perf-y += builtin-diff.o
 perf-y += builtin-evlist.o
 perf-y += builtin-help.o
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
new file mode 100644
index 0000000..62f6bcb
--- /dev/null
+++ b/tools/perf/Documentation/perf-config.txt
@@ -0,0 +1,418 @@
+perf-config(1)
+==============
+
+NAME
+----
+perf-config - Get and set variables in configuration file.
+
+SYNOPSIS
+--------
+[verse]
+'perf config' --list
+
+DESCRIPTION
+-----------
+You can manage variables in configuration file with this command.
+
+OPTIONS
+-------
+
+-l::
+--list::
+	Show all variables with key and value into each sections.
+
+CONFIGURATION FILE
+------------------
+
+The Perf configuration file contain many variables which can make
+the perf command's action more effective, more skilful.
+The '$HOME/.perfconfig' file is used to store a per-user configuration.
+The file 'etc/perfconfig' or '$(sysconfdir)/perfconfig' can be used to
+store a system-wide default configuration.
+
+The variables are divided into sections. In each sections, the variables
+can contain a key and values.
+
+Syntax
+~~~~~~
+
+Example
+~~~~~~~
+
+Given a $HOME/.perfconfig like this:
+
+#
+# This is the config file, and
+# a '#' and ';' character indicates a comment
+#
+
+[colors]
+	# Color variables
+	top = red, default
+	medium = green, default
+	normal = lightgray, default
+	selected = white, lightgray
+	code = blue, default
+	addr = magenta, default
+	root = white, blue
+
+[tui]
+	# Defaults if linked with libslang
+	report = on
+	annotate = on
+	top = on
+
+[buildid]
+	# Default, disable using /dev/null
+	dir = /root/.debug
+
+[annotate]
+	# Defaults
+	hide_src_code = false
+	use_offset = true
+	jump_arrows = true
+	show_nr_jumps = false
+
+[help]
+	# Format can be man, info, web or html
+	format = man
+	autocorrect = 0
+
+[ui]
+	show-headers= true
+
+[call-graph]
+	# fp (framepointer), dwarf
+	record-mode = fp
+	print-type = graph
+	order = caller
+	sort-key = function
+
+Variables
+~~~~~~~~~
+
+colors.*::
+	Color variables can appoint colors of the output which is printed out
+	from ‘report’, ‘top’,’annotate’ on tui.
+	Color variables is composed of foreground and background
+	and should have two values for them. If you want to set as colors
+	of your terminal, you should use ‘default’ for color value.
+        The kind of color which can be used as below.
+	red, green, default, black, blue, white, magenta, lightgray
+
+	colors.top::
+		‘top’ means a overhead percentage which has more than 5%.
+		And values of it’s variable specify colors of percentage.
+		Basic key values are foreground-color ’red’ and
+		background-color ’default’.
+	colors.medium::
+		‘medium’ means a overhead percentage which has more than 0.5%.
+		Default values are ’green’ and ’default’.
+	colors.normal::
+		‘normal’ means rest of overhead percentages
+		except ‘top’, ‘medium’, ‘selected’.
+		Default values are ’lightgray’ and ’default’.
+	colors.selected::
+		This appoint colors for forcussed one of the output list
+		from sub-commands (top,report,annotate).
+		Default values are ’white’ and ’lightgray’.
+	colors.code::
+		Colors for a arrow and lines on jumping by assembly code
+		such as ‘jns’,’jmp’,’jane’,etc. Default values are ‘blue’, ‘default’.
+	colors.addr::
+		This appoint colors for addresses from a sub-command ’annotate’.
+		Default values are ‘magenta’, ‘default’.
+	colors.root::
+		Colors for headers in the output of a sub-command ‘top’.
+		Default values are ‘white’, ‘blue’.
+
+tui.*::
+	A boolean value that controls launching TUI browser for each subcommand.
+	By default, TUI is enabled if perf detects a needed library during build
+	and this config option can control it.  Available subcommands are 'top',
+	'report' and 'annotate'.
+
+gtk.*::
+	A boolean value that controls launching GTK+2 GUI browser for
+	each subcommand.  By default, TUI is enabled if perf detects a
+	needed library during build and this config option can control
+	it.  Available subcommands are 'top', 'report' and 'annotate'.
+
+buildid.*::
+	buildid.dir::
+		Each executable or shared library built with each program is assigned
+		a unique identification as build-id. The option means a path where
+		build-id information can be saved.
+		The default is $HOME/.debug
+
+annotate.*::
+	There’re options which work with a ’annotate’ sub-command.
+	This Options is in control of addresses, jump function, source code
+	in lines of assembly code from a specific program.
+
+	annotate.hide_src_code::
+		If a program which is analyzed has source code of itself,
+		this option let ‘annotate’ print a list of assembly code with the source code.
+		For example, let’s see a part of a program. There’re four lines.
+		If this option is ‘false’, they can be printed
+		without source code from a program as below.
+
+		│        push   %rbp
+		│        mov    %rsp,%rbp
+		│        sub    $0x10,%rsp
+		│        mov    (%rdi),%rdx
+
+		But if this option is ‘true’, source code of the part
+		can be also printed as below.
+
+		│      struct rb_node *rb_next(const struct rb_node *node)
+		│      {
+		│        push   %rbp
+		│        mov    %rsp,%rbp
+		│        sub    $0x10,%rsp
+		│              struct rb_node *parent;
+		│
+		│              if (RB_EMPTY_NODE(node))
+		│        mov    (%rdi),%rdx
+		│              return n;
+
+        annotate.use_offset::
+		Basing on a first address of a loaded function, offset can be used.
+		Instead of using original addresses of assembly code,
+		addresses subtracted from a base address can be printed.
+		Let’s illustrate a example.
+		If a base address is 0XFFFFFFFF81624d50 as below,
+
+		ffffffff81624d50 <load0>
+
+		a address on assembly code has a specific absolute address as below
+
+		ffffffff816250b8:│  mov    0x8(%r14),%rdi
+
+		but if use_offset is ’true’, a address subtracted from a base address is printed.
+		The default is true.
+
+		             368:│  mov    0x8(%r14),%rdi
+
+	annotate.jump_arrows::
+		There’re jump instruction among assembly code.
+		Depending on a boolean value of jump_arrows,
+		arrows can be printed or not which represent
+		where do the instruction jump into as below.
+
+		│     ┌──jmp    1333
+		│     │  xchg   %ax,%ax
+		│1330:│  mov    %r15,%r10
+		│1333:└─→cmp    %r15,%r14
+
+		If jump_arrow is ‘false’, the arrows isn’t printed as below.
+
+		│      ↓ jmp    1333
+		│        xchg   %ax,%ax
+		│1330:   mov    %r15,%r10
+		│1333:   cmp    %r15,%r14
+
+        annotate.show_nr_jumps::
+		Let’s see a part of assembly code.
+
+		│1382:   movb   $0x1,-0x270(%rbp)
+
+		If use this, the number of branches branching to that address can be printed as below.
+
+		│1 1382:   movb   $0x1,-0x270(%rbp)
+
+help.*::
+	help.format:: = man
+		A format of manual page can be ‘man’, ‘info’, ‘web’ or ‘html’.
+		’man’ is default.
+	help.autocorrect:: = 0
+		Automatically correct and execute mistyped commands after
+		waiting for the given number of deciseconds (0.1 sec).
+		Let's see a example. If a mistyped sub-command is executed like 'perf mistyped-command'
+		and this option is 0, the output is as below.
+
+		perf: 'mistyped-command' is not a perf-command. See 'perf --help’.
+
+		Or if this option is more than 1, the output can be such as.
+
+		WARNING: You called a perf program named 'mistyped-command', which does not exist.
+		Continuing under the assumption that you meant 'with-kcore'
+		in 0.1 seconds automatically...
+		Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]
+		<perf sub-command> can be record, script, report or inject
+		    or: perf-with-kcore fix_buildid_cache_permissions
+
+hist.*::
+	hist.percentage::
+		This option control a way to calcurate overhead of filtered entries -
+		that means the value of this option is effective only if there's a
+		filter (by comm, dso or symbol name).  Suppose a following example:
+
+		       Overhead  Symbols
+		       ........  .......
+		        33.33%     foo
+		        33.33%     bar
+		        33.33%     baz
+
+	       This is an original overhead and we'll filter out the first 'foo'
+	       entry.  The value of 'relative' would increase the overhead of 'bar'
+	       and 'baz' to 50.00% for each, while 'absolute' would show their
+	       current overhead (33.33%).
+
+ui.*::
+	ui.show-headers::
+		There’re columns as header ‘Overhead’, ‘Children’, ‘Shared Object’, ‘Symbol’, ’self’.
+		If this option is false, they are hiden.
+
+call-graph.*::
+	When sub-commands ‘top’ and ‘report’ work with -g/—-children
+	there’re options in control of call-graph.
+
+	call-graph.record-mode::
+		The record-mode can be ‘fp’ (frame pointer) and ‘dwarf’.
+		The value of 'dwarf' is effective only if perf detect needed library
+		(libunwind or a recent version of libdw).  Also it doesn't *require*
+		the dump-size option since it can use the default value of 8192 if
+		missing.
+
+	call-graph.dump-size::
+		The size of stack to dump in order to do post-unwinding.  Default is 8192 (byte).
+		When using dwarf into record-mode this option should have a value.
+
+	call-graph.print-type::
+		The print-types can be graph (graph absolute), fractal (graph relative), flat.
+		This option controls a way to show overhead for each callchain entry.
+		Suppose a following example.
+
+		Overhead  Symbols
+		........  .......
+		  40.00%  foo
+		      |
+		      --- foo
+		      |
+		      |--50.00%-- bar
+		      |           main
+		      |
+		      --50.00%-- baz
+		                 main
+
+		This output is a default format which is 'fractal'.  The 'foo' came
+		from 'bar' and 'baz' exactly half and half so 'fractal' shows 50.00%
+		for each (meaning that it assumes 100% total overhead of 'foo').
+
+		The 'graph' uses absolute overhead value of 'foo' as total so each of
+		'bar' and 'baz' callchain will have 20.00% of overhead.
+
+	call-graph.order::
+		This option controls print order of callchains.  The default is
+		'callee' which means callee is printed at top and then followed by its
+		caller and so on.  The 'caller' prints it in reverse order.
+
+	call-graph.sort-key::
+		The callchains are merged if they contain same information.
+		The sort-key option determines a way to compare the callchains.
+		A value of 'sort-key' can be 'function' or 'address’.
+		The default is ‘function’.
+
+	call-graph.threshold::
+		When there're many callchains it'd print tons of lines.  So perf omits
+		small callchains under a certain overhead (threshold) and this option
+		control the threashold.  Default is 0.5 (%).
+
+	call-graph.print-limit::
+		This is another way to control the number of callchains printed for a
+		single entry.  Default is 0 which means no limitation.
+
+report.*::
+	report.percent-limit::
+		This one is mostly same as call-graph.threshold but works for
+		histogram entries.  Entries have overhead lower than this percentage
+		will not be printed.  Default is 0.
+		If percent-limit is 70, the output which has percentages of
+		each overhead above 70% can be printed.
+
+	report.queue-size::
+		option to setup the maximum allocation size for session's
+		ordered events queue, if not set there's no default limit
+
+	report.children::
+		The children means that functions called from another function.
+		If the option is true, accumulate callchain of children and show total overhead.
+		For example, there’re three functions like below.
+
+		 void foo(void) {
+		   /* do something */
+		 }
+
+		 void bar(void) {
+		   /* do something */
+		   foo();
+		 }
+
+		 int main(void) {
+		   bar()
+		   return 0;
+		 }
+
+		Defaultly the output of sub-commands such as ’top’, ‘report’ and ‘annotate’
+		depend on a sort of overhead into each functions as below.
+
+		Overhead  Symbol
+		........  .....................
+		  60.00%  foo
+		          |
+		          --- foo
+		              bar
+		              main
+		              __libc_start_main
+
+		  40.00%  bar
+		          |
+		          --- bar
+		              main
+		              __libc_start_main
+
+		But if this option is true, the sort is changed into a sort of
+		overhead into each children group of each function  reciting all functions
+		from a first parent function till a last child function like below.
+		And it requires -g/--call-graph option enabled
+
+		Children      Self  Symbol
+		........  ........  ....................
+		 100.00%     0.00%  __libc_start_main
+		          |
+		          --- __libc_start_main
+
+		 100.00%     0.00%  main
+		          |
+		          --- main
+		              __libc_start_main
+
+		 100.00%    40.00%  bar
+		          |
+		          --- bar
+		              main
+		              __libc_start_main
+
+		  60.00%    60.00%  foo
+		          |
+		          --- foo
+		              bar
+		              main
+		              __libc_start_main
+
+top.*::
+	top.children::
+		This option means same as report.children.
+		So it is true, the output of ‘top’ is rearranged by each overhead into children group.
+
+man.*::
+	man.viewer::
+
+pager.*::
+	pager.report::
+	pager
+
+SEE ALSO
+--------
+linkperf:perf[1]
diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
index 767ea24..853aa20 100644
--- a/tools/perf/Documentation/perfconfig.example
+++ b/tools/perf/Documentation/perfconfig.example
@@ -1,29 +1,72 @@
 [colors]
-
-	# These were the old defaults
-	top = red, lightgray
-	medium = green, lightgray
-	normal = black, lightgray
-	selected = lightgray, magenta
-	code = blue, lightgray
-	addr = magenta, lightgray
+	# There are types of colors which are red,
+	# green, default, black, blue,
+	# white, magenta, lightgray
+	# The default is like below
+	top = red, default
+	medium = green, default
+	normal = lightgray, default
+	selected = white, lightgray
+	code = blue, default
+	addr = magenta, default
+	root = white, blue
 
 [tui]
-
 	# Defaults if linked with libslang
 	report = on
 	annotate = on
 	top = on
 
 [buildid]
-
 	# Default, disable using /dev/null
 	dir = /root/.debug
 
 [annotate]
-
 	# Defaults
 	hide_src_code = false
 	use_offset = true
 	jump_arrows = true
 	show_nr_jumps = false
+
+[gtk]
+	report = off
+	annotate = off
+	#top = off
+
+[pager]
+	# That a 'cmd' is true mean to use "pager or less"
+	cmd = true
+	report = false
+	diff = true
+
+[help]
+	# Format can be man, info, web or html
+	format = man
+	autocorrect = 0
+
+[hist]
+	# a value of 'percentage' can be 'relative' or 'absolute'
+	percentage = absolute
+
+[ui]
+	show-headers= true
+
+[call-graph]
+	# fp (framepointer), dwarf
+	record-mode = fp
+
+	# graph (graph absolute), flat, fractal (graph relative)
+	print-type = fractal
+
+	# caller, callee
+	order = caller
+
+	# function, address
+	sort-key = function
+
+[report]
+	percent-limit = 1
+	children = false
+
+[top]
+	children = true
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
new file mode 100644
index 0000000..494bd73
--- /dev/null
+++ b/tools/perf/builtin-config.c
@@ -0,0 +1,67 @@
+/*
+ * builtin-config.c
+ *
+ * Copyright (C) 2015, Taeung Song <treeze.taeung@gmail.com>
+ *
+ */
+#include "builtin.h"
+
+#include "perf.h"
+
+#include "util/cache.h"
+#include "util/parse-options.h"
+#include "util/util.h"
+#include "util/debug.h"
+
+static struct {
+	bool list_action;
+} params;
+
+static const char * const config_usage[] = {
+	"perf config [options]",
+	NULL
+};
+static const struct option config_options[] = {
+	OPT_BOOLEAN('l', "list", &params.list_action, "list up current configurations"),
+	OPT_END()
+};
+
+static void check_argc(int argc, int min, int max)
+{
+	if (argc >= min && argc <= max)
+		return;
+	error("wrong number of arguments");
+	usage_with_options(config_usage, config_options);
+}
+
+static int show_config(const char *key, const char *value,
+			   void *cb __maybe_unused)
+{
+	if (value)
+		printf("%s=%s\n", key, value);
+	else
+		printf("%s\n", key);
+
+	return 0;
+}
+
+int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+	int ret = 0;
+
+	argc = parse_options(argc, argv, config_options, config_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+	if (argc > 0) {
+		if (strcmp(argv[0], "-") == 0) {
+			pr_warning("  Error: '-' is not supported.\n");
+			usage_with_options(config_usage, config_options);
+		}
+	}
+
+	if (params.list_action) {
+		check_argc(argc, 0, 0);
+		ret = perf_config(show_config, NULL);
+	}
+
+	return ret;
+}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 3688ad2..3f871b5 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -17,6 +17,7 @@ extern int cmd_annotate(int argc, const char **argv, const char *prefix);
 extern int cmd_bench(int argc, const char **argv, const char *prefix);
 extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix);
 extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
+extern int cmd_config(int argc, const char **argv, const char *prefix);
 extern int cmd_diff(int argc, const char **argv, const char *prefix);
 extern int cmd_evlist(int argc, const char **argv, const char *prefix);
 extern int cmd_help(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 00fcaf8..acc3ea7 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -9,6 +9,7 @@ perf-buildid-cache		mainporcelain common
 perf-buildid-list		mainporcelain common
 perf-data			mainporcelain common
 perf-diff			mainporcelain common
+perf-config			mainporcelain common
 perf-evlist			mainporcelain common
 perf-inject			mainporcelain common
 perf-kmem			mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index b857fcb..604fa4a 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -37,6 +37,7 @@ struct cmd_struct {
 static struct cmd_struct commands[] = {
 	{ "buildid-cache", cmd_buildid_cache, 0 },
 	{ "buildid-list", cmd_buildid_list, 0 },
+	{ "config",	cmd_config,	0 },
 	{ "diff",	cmd_diff,	0 },
 	{ "evlist",	cmd_evlist,	0 },
 	{ "help",	cmd_help,	0 },
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2015-04-19  3:43 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-12 14:44 [PATCH 1/2] perf tools: Add 'perf-config' command Taeung Song
2015-04-12 14:44 ` [PATCH 2/2] perf tools: Add a option 'remove' to perf-config and features which get or set a config variable Taeung Song
2015-04-13  6:55   ` Namhyung Kim
     [not found]     ` <6F8981BC-A058-4D84-93FC-B7CB8ADDCC53@gmail.com>
2015-04-19  3:42       ` Namhyung Kim
2015-04-13  6:16 ` [PATCH 1/2] perf tools: Add 'perf-config' command Namhyung Kim
     [not found]   ` <5CB87CAF-B6EE-4AE0-BC3C-45CEF14C28EC@gmail.com>
2015-04-19  3:27     ` Namhyung Kim
     [not found]   ` <70EA4387-5059-4026-8819-039474865EEE@gmail.com>
2015-04-19  3:34     ` Namhyung Kim
  -- strict thread matches above, loose matches on Subject: below --
2015-04-09 14:26 Taeung Song
2015-04-09 15:57 ` Arnaldo Carvalho de Melo
2015-04-10  8:53 ` Jiri Olsa
2015-04-04 17:41 Taeung Song
2015-04-07 17:57 ` Jiri Olsa

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.