Skip to content

Commit e8536dd

Browse files
committed
perf ftrace latency: Introduce --bucket-range to ask for linear bucketing
In addition to showing it exponentially, using log2() to figure out the histogram index, allow for showing it linearly: The preexisting more, the default: # perf ftrace latency --use-nsec --use-bpf \ -T switch_mm_irqs_off -a sleep 2 # DURATION | COUNT | GRAPH | 0 - 1 ns | 0 | | 1 - 2 ns | 0 | | 2 - 4 ns | 0 | | 4 - 8 ns | 0 | | 8 - 16 ns | 0 | | 16 - 32 ns | 0 | | 32 - 64 ns | 0 | | 64 - 128 ns | 238 | # | 128 - 256 ns | 1704 | ########## | 256 - 512 ns | 672 | ### | 512 - 1024 ns | 4458 | ########################## | 1 - 2 us | 677 | #### | 2 - 4 us | 5 | | 4 - 8 us | 0 | | 8 - 16 us | 0 | | 16 - 32 us | 0 | | 32 - 64 us | 0 | | 64 - 128 us | 0 | | 128 - 256 us | 0 | | 256 - 512 us | 0 | | 512 - 1024 us | 0 | | 1 - ... ms | 0 | | # The new histogram mode: # perf ftrace latency --bucket-range=150 --use-nsec --use-bpf \ -T switch_mm_irqs_off -a sleep 2 # DURATION | COUNT | GRAPH | 0 - 1 ns | 0 | | 1 - 151 ns | 265 | # | 151 - 301 ns | 1797 | ########### | 301 - 451 ns | 258 | # | 451 - 601 ns | 289 | # | 601 - 751 ns | 2049 | ############# | 751 - 901 ns | 967 | ###### | 901 - 1051 ns | 513 | ### | 1.05 - 1.20 us | 114 | | 1.20 - 1.35 us | 559 | ### | 1.35 - 1.50 us | 189 | # | 1.50 - 1.65 us | 137 | | 1.65 - 1.80 us | 32 | | 1.80 - 1.95 us | 2 | | 1.95 - 2.10 us | 0 | | 2.10 - 2.25 us | 1 | | 2.25 - 2.40 us | 1 | | 2.40 - 2.55 us | 0 | | 2.55 - 2.70 us | 0 | | 2.70 - 2.85 us | 0 | | 2.85 - 3.00 us | 1 | | 3.00 - ... us | 4 | | # Co-developed-by: Gabriele Monaco <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Clark Williams <[email protected]> Cc: Ian Rogers <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kan Liang <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Gabriele Monaco <[email protected]> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 12115c6 commit e8536dd

File tree

5 files changed

+73
-13
lines changed

5 files changed

+73
-13
lines changed

tools/perf/Documentation/perf-ftrace.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ OPTIONS for 'perf ftrace latency'
148148
--use-nsec::
149149
Use nano-second instead of micro-second as a base unit of the histogram.
150150

151+
--bucket-range=::
152+
Bucket range in ms or ns (according to -n/--use-nsec), default is log2() mode.
153+
151154

152155
OPTIONS for 'perf ftrace profile'
153156
---------------------------------

tools/perf/builtin-ftrace.c

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -777,9 +777,17 @@ static void make_histogram(struct perf_ftrace *ftrace, int buckets[],
777777
if (ftrace->use_nsec)
778778
num *= 1000;
779779

780-
i = log2(num);
781-
if (i < 0)
780+
if (!ftrace->bucket_range) {
781+
i = log2(num);
782+
if (i < 0)
783+
i = 0;
784+
} else {
785+
// Less than 1 unit (ms or ns), or, in the future,
786+
// than the min latency desired.
782787
i = 0;
788+
if (num > 0) // 1st entry: [ 1 unit .. bucket_range units ]
789+
i = num / ftrace->bucket_range + 1;
790+
}
783791
if (i >= NUM_BUCKET)
784792
i = NUM_BUCKET - 1;
785793

@@ -815,28 +823,58 @@ static void display_histogram(struct perf_ftrace *ftrace, int buckets[])
815823
" DURATION ", "COUNT", bar_total, "GRAPH");
816824

817825
bar_len = buckets[0] * bar_total / total;
818-
printf(" %4d - %-4d %s | %10d | %.*s%*s |\n",
826+
827+
printf(" %4d - %4d %s | %10d | %.*s%*s |\n",
819828
0, 1, use_nsec ? "ns" : "us", buckets[0], bar_len, bar, bar_total - bar_len, "");
820829

821830
for (i = 1; i < NUM_BUCKET - 1; i++) {
822-
int start = (1 << (i - 1));
823-
int stop = 1 << i;
831+
int start, stop;
824832
const char *unit = use_nsec ? "ns" : "us";
825833

826-
if (start >= 1024) {
827-
start >>= 10;
828-
stop >>= 10;
829-
unit = use_nsec ? "us" : "ms";
834+
if (!ftrace->bucket_range) {
835+
start = (1 << (i - 1));
836+
stop = 1 << i;
837+
838+
if (start >= 1024) {
839+
start >>= 10;
840+
stop >>= 10;
841+
unit = use_nsec ? "us" : "ms";
842+
}
843+
} else {
844+
start = (i - 1) * ftrace->bucket_range + 1;
845+
stop = i * ftrace->bucket_range + 1;
846+
847+
if (start >= 1000) {
848+
double dstart = start / 1000.0,
849+
dstop = stop / 1000.0;
850+
printf(" %4.2f - %-4.2f", dstart, dstop);
851+
unit = use_nsec ? "us" : "ms";
852+
goto print_bucket_info;
853+
}
830854
}
855+
856+
printf(" %4d - %4d", start, stop);
857+
print_bucket_info:
831858
bar_len = buckets[i] * bar_total / total;
832-
printf(" %4d - %-4d %s | %10d | %.*s%*s |\n",
833-
start, stop, unit, buckets[i], bar_len, bar,
859+
printf(" %s | %10d | %.*s%*s |\n", unit, buckets[i], bar_len, bar,
834860
bar_total - bar_len, "");
835861
}
836862

837863
bar_len = buckets[NUM_BUCKET - 1] * bar_total / total;
838-
printf(" %4d - %-4s %s | %10d | %.*s%*s |\n",
839-
1, "...", use_nsec ? "ms" : " s", buckets[NUM_BUCKET - 1],
864+
if (!ftrace->bucket_range) {
865+
printf(" %4d - %-4s %s", 1, "...", use_nsec ? "ms" : "s ");
866+
} else {
867+
int upper_outlier = (NUM_BUCKET - 2) * ftrace->bucket_range;
868+
869+
if (upper_outlier >= 1000) {
870+
double dstart = upper_outlier / 1000.0;
871+
872+
printf(" %4.2f - %-4s %s", dstart, "...", use_nsec ? "us" : "ms");
873+
} else {
874+
printf(" %4d - %4s %s", upper_outlier, "...", use_nsec ? "ns" : "us");
875+
}
876+
}
877+
printf(" | %10d | %.*s%*s |\n", buckets[NUM_BUCKET - 1],
840878
bar_len, bar, bar_total - bar_len, "");
841879

842880
}
@@ -1558,6 +1596,8 @@ int cmd_ftrace(int argc, const char **argv)
15581596
#endif
15591597
OPT_BOOLEAN('n', "use-nsec", &ftrace.use_nsec,
15601598
"Use nano-second histogram"),
1599+
OPT_UINTEGER(0, "bucket-range", &ftrace.bucket_range,
1600+
"Bucket range in ms or ns (-n/--use-nsec), default is log2() mode"),
15611601
OPT_PARENT(common_options),
15621602
};
15631603
const struct option profile_options[] = {

tools/perf/util/bpf_ftrace.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ int perf_ftrace__latency_prepare_bpf(struct perf_ftrace *ftrace)
3636
return -1;
3737
}
3838

39+
skel->rodata->bucket_range = ftrace->bucket_range;
40+
3941
/* don't need to set cpu filter for system-wide mode */
4042
if (ftrace->target.cpu_list) {
4143
ncpus = perf_cpu_map__nr(ftrace->evlist->core.user_requested_cpus);

tools/perf/util/bpf_skel/func_latency.bpf.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ int enabled = 0;
4141
const volatile int has_cpu = 0;
4242
const volatile int has_task = 0;
4343
const volatile int use_nsec = 0;
44+
const volatile unsigned int bucket_range;
4445

4546
SEC("kprobe/func")
4647
int BPF_PROG(func_begin)
@@ -100,12 +101,25 @@ int BPF_PROG(func_end)
100101
if (delta < 0)
101102
return 0;
102103

104+
if (bucket_range != 0) {
105+
delta /= cmp_base;
106+
// Less than 1 unit (ms or ns), or, in the future,
107+
// than the min latency desired.
108+
key = 0;
109+
if (delta > 0) { // 1st entry: [ 1 unit .. bucket_range units )
110+
key = delta / bucket_range + 1;
111+
if (key >= NUM_BUCKET)
112+
key = NUM_BUCKET - 1;
113+
}
114+
goto do_lookup;
115+
}
103116
// calculate index using delta
104117
for (key = 0; key < (NUM_BUCKET - 1); key++) {
105118
if (delta < (cmp_base << key))
106119
break;
107120
}
108121

122+
do_lookup:
109123
hist = bpf_map_lookup_elem(&latency, &key);
110124
if (!hist)
111125
return 0;

tools/perf/util/ftrace.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct perf_ftrace {
2020
unsigned long percpu_buffer_size;
2121
bool inherit;
2222
bool use_nsec;
23+
unsigned int bucket_range;
2324
int graph_depth;
2425
int func_stack_trace;
2526
int func_irq_info;

0 commit comments

Comments
 (0)