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

Configure Feed

Select the types of activity you want to include in your feed.

perf lock: Add -c/--combine-locks option

The -c or --combine-locks option is to merge lock instances in the
same class into a single entry. It compares the name of the locks
and marks duplicated entries using lock_stat->combined.

# perf lock report
Name acquired contended avg wait (ns) total wait (ns) max wait (ns) min wait (ns)

rcu_read_lock 251225 0 0 0 0 0
&(ei->i_block_re... 8731 0 0 0 0 0
&sb->s_type->i_l... 8731 0 0 0 0 0
hrtimer_bases.lock 5261 0 0 0 0 0
hrtimer_bases.lock 2626 0 0 0 0 0
hrtimer_bases.lock 1953 0 0 0 0 0
hrtimer_bases.lock 1382 0 0 0 0 0
cpu_hotplug_lock 1350 0 0 0 0 0
hrtimer_bases.lock 1273 0 0 0 0 0
hrtimer_bases.lock 1269 0 0 0 0 0

# perf lock report -c
Name acquired contended avg wait (ns) total wait (ns) max wait (ns) min wait (ns)

rcu_read_lock 251225 0 0 0 0 0
hrtimer_bases.lock 39450 0 0 0 0 0
&sb->s_type->i_l... 10301 1 662 662 662 662
ptlock_ptr(page) 10173 2 701 1402 760 642
&(ei->i_block_re... 8732 0 0 0 0 0
&xa->xa_lock 8088 0 0 0 0 0
&base->lock 6705 0 0 0 0 0
&p->pi_lock 5549 0 0 0 0 0
&dentry->d_lockr... 5010 4 1274 5097 1844 789
&ep->lock 3958 0 0 0 0 0

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220127000050.3011493-6-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Namhyung Kim and committed by
Arnaldo Carvalho de Melo
0d435bf8 ba8a56c7

+72
+4
tools/perf/Documentation/perf-lock.txt
··· 54 54 Sorting key. Possible values: acquired (default), contended, 55 55 avg_wait, wait_total, wait_max, wait_min. 56 56 57 + -c:: 58 + --combine-locks:: 59 + Merge lock instances in the same class (based on name). 60 + 57 61 INFO OPTIONS 58 62 ------------ 59 63
+68
tools/perf/builtin-lock.c
··· 65 65 u64 wait_time_max; 66 66 67 67 int discard; /* flag of blacklist */ 68 + int combined; 68 69 }; 69 70 70 71 /* ··· 115 114 }; 116 115 117 116 static struct rb_root thread_stats; 117 + 118 + static bool combine_locks; 118 119 119 120 static struct thread_stat *thread_stat_find(u32 tid) 120 121 { ··· 244 241 245 242 static int (*compare)(struct lock_stat *, struct lock_stat *); 246 243 244 + static struct rb_root sorted; /* place to store intermediate data */ 247 245 static struct rb_root result; /* place to store sorted data */ 248 246 249 247 #define DEF_KEY_LOCK(name, fn_suffix) \ ··· 278 274 return -1; 279 275 } 280 276 277 + static void combine_lock_stats(struct lock_stat *st) 278 + { 279 + struct rb_node **rb = &sorted.rb_node; 280 + struct rb_node *parent = NULL; 281 + struct lock_stat *p; 282 + int ret; 283 + 284 + while (*rb) { 285 + p = container_of(*rb, struct lock_stat, rb); 286 + parent = *rb; 287 + 288 + if (st->name && p->name) 289 + ret = strcmp(st->name, p->name); 290 + else 291 + ret = !!st->name - !!p->name; 292 + 293 + if (ret == 0) { 294 + p->nr_acquired += st->nr_acquired; 295 + p->nr_contended += st->nr_contended; 296 + p->wait_time_total += st->wait_time_total; 297 + 298 + if (p->nr_contended) 299 + p->avg_wait_time = p->wait_time_total / p->nr_contended; 300 + 301 + if (p->wait_time_min > st->wait_time_min) 302 + p->wait_time_min = st->wait_time_min; 303 + if (p->wait_time_max < st->wait_time_max) 304 + p->wait_time_max = st->wait_time_max; 305 + 306 + st->combined = 1; 307 + return; 308 + } 309 + 310 + if (ret < 0) 311 + rb = &(*rb)->rb_left; 312 + else 313 + rb = &(*rb)->rb_right; 314 + } 315 + 316 + rb_link_node(&st->rb, parent, rb); 317 + rb_insert_color(&st->rb, &sorted); 318 + } 319 + 281 320 static void insert_to_result(struct lock_stat *st, 282 321 int (*bigger)(struct lock_stat *, struct lock_stat *)) 283 322 { 284 323 struct rb_node **rb = &result.rb_node; 285 324 struct rb_node *parent = NULL; 286 325 struct lock_stat *p; 326 + 327 + if (combine_locks && st->combined) 328 + return; 287 329 288 330 while (*rb) { 289 331 p = container_of(*rb, struct lock_stat, rb); ··· 883 833 return err; 884 834 } 885 835 836 + static void combine_result(void) 837 + { 838 + unsigned int i; 839 + struct lock_stat *st; 840 + 841 + if (!combine_locks) 842 + return; 843 + 844 + for (i = 0; i < LOCKHASH_SIZE; i++) { 845 + hlist_for_each_entry(st, &lockhash_table[i], hash_entry) { 846 + combine_lock_stats(st); 847 + } 848 + } 849 + } 850 + 886 851 static void sort_result(void) 887 852 { 888 853 unsigned int i; ··· 961 896 if (display_info) /* used for info subcommand */ 962 897 err = dump_info(); 963 898 else { 899 + combine_result(); 964 900 sort_result(); 965 901 print_result(); 966 902 } ··· 1036 970 OPT_STRING('k', "key", &sort_key, "acquired", 1037 971 "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"), 1038 972 /* TODO: type */ 973 + OPT_BOOLEAN('c', "combine-locks", &combine_locks, 974 + "combine locks in the same class"), 1039 975 OPT_PARENT(lock_options) 1040 976 }; 1041 977