Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf lock: Add -k and -F options to 'contention' subcommand

Like perf lock report, add -k/--key and -F/--field options to control
output formatting and sorting. Note that it has slightly different
default options as some fields are not available and to optimize the
screen space.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Waiman Long <longman@redhat.com>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20220725183124.368304-5-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Namhyung Kim and committed by
Arnaldo Carvalho de Melo
79079f21 528b9cab

+55 -11
+15
tools/perf/Documentation/perf-lock.txt
··· 105 105 --map:: 106 106 dump map of lock instances (address:name table) 107 107 108 + CONTENTION OPTIONS 109 + -------------- 110 + 111 + -k:: 112 + --key=<value>:: 113 + Sorting key. Possible values: contended, wait_total (default), 114 + wait_max, wait_min, avg_wait. 115 + 116 + -F:: 117 + --field=<value>:: 118 + Output fields. By default it shows all but the wait_min fields 119 + and users can customize that using this. Possible values: 120 + contended, wait_total, wait_max, wait_min, avg_wait. 121 + 122 + 108 123 SEE ALSO 109 124 -------- 110 125 linkperf:perf[1]
+40 -11
tools/perf/builtin-lock.c
··· 362 362 363 363 #define DEF_KEY_LOCK(name, header, fn_suffix, len) \ 364 364 { #name, header, len, lock_stat_key_ ## fn_suffix, lock_stat_key_print_ ## fn_suffix, {} } 365 - struct lock_key keys[] = { 365 + static struct lock_key report_keys[] = { 366 366 DEF_KEY_LOCK(acquired, "acquired", nr_acquired, 10), 367 367 DEF_KEY_LOCK(contended, "contended", nr_contended, 10), 368 368 DEF_KEY_LOCK(avg_wait, "avg wait", avg_wait_time, 12), ··· 374 374 { } 375 375 }; 376 376 377 - static int select_key(void) 377 + static struct lock_key contention_keys[] = { 378 + DEF_KEY_LOCK(contended, "contended", nr_contended, 10), 379 + DEF_KEY_LOCK(wait_total, "total wait", wait_time_total, 12), 380 + DEF_KEY_LOCK(wait_max, "max wait", wait_time_max, 12), 381 + DEF_KEY_LOCK(wait_min, "min wait", wait_time_min, 12), 382 + DEF_KEY_LOCK(avg_wait, "avg wait", avg_wait_time, 12), 383 + 384 + /* extra comparisons much complicated should be here */ 385 + { } 386 + }; 387 + 388 + static int select_key(bool contention) 378 389 { 379 390 int i; 391 + struct lock_key *keys = report_keys; 392 + 393 + if (contention) 394 + keys = contention_keys; 380 395 381 396 for (i = 0; keys[i].name; i++) { 382 397 if (!strcmp(keys[i].name, sort_key)) { ··· 409 394 return -1; 410 395 } 411 396 412 - static int add_output_field(struct list_head *head, char *name) 397 + static int add_output_field(bool contention, char *name) 413 398 { 414 399 int i; 400 + struct lock_key *keys = report_keys; 401 + 402 + if (contention) 403 + keys = contention_keys; 415 404 416 405 for (i = 0; keys[i].name; i++) { 417 406 if (strcmp(keys[i].name, name)) ··· 423 404 424 405 /* prevent double link */ 425 406 if (list_empty(&keys[i].list)) 426 - list_add_tail(&keys[i].list, head); 407 + list_add_tail(&keys[i].list, &lock_keys); 427 408 428 409 return 0; 429 410 } ··· 432 413 return -1; 433 414 } 434 415 435 - static int setup_output_field(const char *str) 416 + static int setup_output_field(bool contention, const char *str) 436 417 { 437 418 char *tok, *tmp, *orig; 438 419 int i, ret = 0; 420 + struct lock_key *keys = report_keys; 421 + 422 + if (contention) 423 + keys = contention_keys; 439 424 440 425 /* no output field given: use all of them */ 441 426 if (str == NULL) { ··· 456 433 return -ENOMEM; 457 434 458 435 while ((tok = strsep(&tmp, ",")) != NULL){ 459 - ret = add_output_field(&lock_keys, tok); 436 + ret = add_output_field(contention, tok); 460 437 if (ret < 0) 461 438 break; 462 439 } ··· 1632 1609 goto out_delete; 1633 1610 } 1634 1611 1635 - if (setup_output_field(output_fields)) 1612 + if (setup_output_field(false, output_fields)) 1636 1613 goto out_delete; 1637 1614 1638 - if (select_key()) 1615 + if (select_key(false)) 1639 1616 goto out_delete; 1640 1617 1641 1618 if (show_thread_stats) ··· 1697 1674 goto out_delete; 1698 1675 } 1699 1676 1700 - if (setup_output_field("contended,wait_total,wait_max,avg_wait")) 1677 + if (setup_output_field(true, output_fields)) 1701 1678 goto out_delete; 1702 1679 1703 - sort_key = "wait_total"; 1704 - if (select_key()) 1680 + if (select_key(true)) 1705 1681 goto out_delete; 1706 1682 1707 1683 aggr_mode = LOCK_AGGR_CALLER; ··· 1839 1817 }; 1840 1818 1841 1819 const struct option contention_options[] = { 1820 + OPT_STRING('k', "key", &sort_key, "wait_total", 1821 + "key for sorting (contended / wait_total / wait_max / wait_min / avg_wait)"), 1822 + OPT_STRING('F', "field", &output_fields, "contended,wait_total,wait_max,avg_wait", 1823 + "output fields (contended / wait_total / wait_max / wait_min / avg_wait)"), 1842 1824 OPT_PARENT(lock_options) 1843 1825 }; 1844 1826 ··· 1902 1876 rc = __cmd_report(true); 1903 1877 } else if (strlen(argv[0]) > 2 && strstarts("contention", argv[0])) { 1904 1878 trace_handler = &contention_lock_ops; 1879 + sort_key = "wait_total"; 1880 + output_fields = "contended,wait_total,wait_max,avg_wait"; 1881 + 1905 1882 if (argc) { 1906 1883 argc = parse_options(argc, argv, contention_options, 1907 1884 contention_usage, 0);