perf lock: Add -F/--field option to control output
The -F/--field option is to customize the list of fields to output: $ perf lock report -F contended,wait_max -k avg_wait Name contended max wait (ns) avg wait (ns) slock-AF_INET6 1 23543 23543 &lruvec->lru_lock 5 18317 11254 slock-AF_INET6 1 10379 10379 rcu_node_1 1 2104 2104 &dentry->d_lockr... 1 1844 1844 &dentry->d_lockr... 1 1672 1672 &newf->file_lock 15 2279 1025 &dentry->d_lockr... 1 792 792 Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: https://lore.kernel.org/r/20220323230259.288494-3-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
64999e4402
commit
4bd9cab59f
@ -54,6 +54,12 @@ REPORT OPTIONS
|
|||||||
Sorting key. Possible values: acquired (default), contended,
|
Sorting key. Possible values: acquired (default), contended,
|
||||||
avg_wait, wait_total, wait_max, wait_min.
|
avg_wait, wait_total, wait_max, wait_min.
|
||||||
|
|
||||||
|
-F::
|
||||||
|
--field=<value>::
|
||||||
|
Output fields. By default it shows all the fields but users can
|
||||||
|
customize that using this. Possible values: acquired, contended,
|
||||||
|
avg_wait, wait_total, wait_max, wait_min.
|
||||||
|
|
||||||
-c::
|
-c::
|
||||||
--combine-locks::
|
--combine-locks::
|
||||||
Merge lock instances in the same class (based on name).
|
Merge lock instances in the same class (based on name).
|
||||||
|
@ -282,6 +282,7 @@ static struct rb_root sorted; /* place to store intermediate data */
|
|||||||
static struct rb_root result; /* place to store sorted data */
|
static struct rb_root result; /* place to store sorted data */
|
||||||
|
|
||||||
static LIST_HEAD(lock_keys);
|
static LIST_HEAD(lock_keys);
|
||||||
|
static const char *output_fields;
|
||||||
|
|
||||||
#define DEF_KEY_LOCK(name, header, fn_suffix, len) \
|
#define DEF_KEY_LOCK(name, header, fn_suffix, len) \
|
||||||
{ #name, header, len, lock_stat_key_ ## fn_suffix, lock_stat_key_print_ ## fn_suffix, {} }
|
{ #name, header, len, lock_stat_key_ ## fn_suffix, lock_stat_key_print_ ## fn_suffix, {} }
|
||||||
@ -304,23 +305,65 @@ static int select_key(void)
|
|||||||
for (i = 0; keys[i].name; i++) {
|
for (i = 0; keys[i].name; i++) {
|
||||||
if (!strcmp(keys[i].name, sort_key)) {
|
if (!strcmp(keys[i].name, sort_key)) {
|
||||||
compare = keys[i].key;
|
compare = keys[i].key;
|
||||||
|
|
||||||
|
/* selected key should be in the output fields */
|
||||||
|
if (list_empty(&keys[i].list))
|
||||||
|
list_add_tail(&keys[i].list, &lock_keys);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_err("Unknown compare key: %s\n", sort_key);
|
pr_err("Unknown compare key: %s\n", sort_key);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int setup_output_field(void)
|
static int add_output_field(struct list_head *head, char *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; keys[i].name; i++)
|
for (i = 0; keys[i].name; i++) {
|
||||||
list_add_tail(&keys[i].list, &lock_keys);
|
if (strcmp(keys[i].name, name))
|
||||||
|
continue;
|
||||||
|
|
||||||
return 0;
|
/* prevent double link */
|
||||||
|
if (list_empty(&keys[i].list))
|
||||||
|
list_add_tail(&keys[i].list, head);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_err("Unknown output field: %s\n", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setup_output_field(const char *str)
|
||||||
|
{
|
||||||
|
char *tok, *tmp, *orig;
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
/* no output field given: use all of them */
|
||||||
|
if (str == NULL) {
|
||||||
|
for (i = 0; keys[i].name; i++)
|
||||||
|
list_add_tail(&keys[i].list, &lock_keys);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; keys[i].name; i++)
|
||||||
|
INIT_LIST_HEAD(&keys[i].list);
|
||||||
|
|
||||||
|
orig = tmp = strdup(str);
|
||||||
|
if (orig == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
while ((tok = strsep(&tmp, ",")) != NULL){
|
||||||
|
ret = add_output_field(&lock_keys, tok);
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(orig);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void combine_lock_stats(struct lock_stat *st)
|
static void combine_lock_stats(struct lock_stat *st)
|
||||||
@ -1002,7 +1045,7 @@ static int __cmd_report(bool display_info)
|
|||||||
goto out_delete;
|
goto out_delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setup_output_field())
|
if (setup_output_field(output_fields))
|
||||||
goto out_delete;
|
goto out_delete;
|
||||||
|
|
||||||
if (select_key())
|
if (select_key())
|
||||||
@ -1090,6 +1133,8 @@ int cmd_lock(int argc, const char **argv)
|
|||||||
const struct option report_options[] = {
|
const struct option report_options[] = {
|
||||||
OPT_STRING('k', "key", &sort_key, "acquired",
|
OPT_STRING('k', "key", &sort_key, "acquired",
|
||||||
"key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
|
"key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
|
||||||
|
OPT_STRING('F', "field", &output_fields, NULL,
|
||||||
|
"output fields (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
|
||||||
/* TODO: type */
|
/* TODO: type */
|
||||||
OPT_BOOLEAN('c', "combine-locks", &combine_locks,
|
OPT_BOOLEAN('c', "combine-locks", &combine_locks,
|
||||||
"combine locks in the same class"),
|
"combine locks in the same class"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user