Commit | Line | Data |
---|---|---|
5c7fc2d2 AS |
1 | /* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com |
2 | * | |
3 | * This program is free software; you can redistribute it and/or | |
4 | * modify it under the terms of version 2 of the GNU General Public | |
5 | * License as published by the Free Software Foundation. | |
6 | */ | |
7 | #include <stdio.h> | |
8 | #include <stdlib.h> | |
9 | #include <signal.h> | |
10 | #include <unistd.h> | |
11 | #include <stdbool.h> | |
12 | #include <string.h> | |
13 | #include <linux/bpf.h> | |
55de1703 | 14 | #include <sys/resource.h> |
e00c7b21 | 15 | |
5c7fc2d2 AS |
16 | #include "libbpf.h" |
17 | #include "bpf_load.h" | |
e00c7b21 | 18 | #include "bpf_util.h" |
5c7fc2d2 AS |
19 | |
20 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) | |
21 | ||
22 | #define SLOTS 100 | |
23 | ||
24 | static void clear_stats(int fd) | |
25 | { | |
e00c7b21 | 26 | unsigned int nr_cpus = bpf_num_possible_cpus(); |
3059303f | 27 | __u64 values[nr_cpus]; |
5c7fc2d2 | 28 | __u32 key; |
5c7fc2d2 | 29 | |
3059303f | 30 | memset(values, 0, sizeof(values)); |
5c7fc2d2 | 31 | for (key = 0; key < SLOTS; key++) |
d40fc181 | 32 | bpf_map_update_elem(fd, &key, values, BPF_ANY); |
5c7fc2d2 AS |
33 | } |
34 | ||
35 | const char *color[] = { | |
36 | "\033[48;5;255m", | |
37 | "\033[48;5;252m", | |
38 | "\033[48;5;250m", | |
39 | "\033[48;5;248m", | |
40 | "\033[48;5;246m", | |
41 | "\033[48;5;244m", | |
42 | "\033[48;5;242m", | |
43 | "\033[48;5;240m", | |
44 | "\033[48;5;238m", | |
45 | "\033[48;5;236m", | |
46 | "\033[48;5;234m", | |
47 | "\033[48;5;232m", | |
48 | }; | |
49 | const int num_colors = ARRAY_SIZE(color); | |
50 | ||
51 | const char nocolor[] = "\033[00m"; | |
52 | ||
53 | const char *sym[] = { | |
54 | " ", | |
55 | " ", | |
56 | ".", | |
57 | ".", | |
58 | "*", | |
59 | "*", | |
60 | "o", | |
61 | "o", | |
62 | "O", | |
63 | "O", | |
64 | "#", | |
65 | "#", | |
66 | }; | |
67 | ||
68 | bool full_range = false; | |
69 | bool text_only = false; | |
70 | ||
71 | static void print_banner(void) | |
72 | { | |
73 | if (full_range) | |
74 | printf("|1ns |10ns |100ns |1us |10us |100us" | |
75 | " |1ms |10ms |100ms |1s |10s\n"); | |
76 | else | |
77 | printf("|1us |10us |100us |1ms |10ms " | |
78 | "|100ms |1s |10s\n"); | |
79 | } | |
80 | ||
81 | static void print_hist(int fd) | |
82 | { | |
e00c7b21 | 83 | unsigned int nr_cpus = bpf_num_possible_cpus(); |
5c7fc2d2 | 84 | __u64 total_events = 0; |
3059303f AS |
85 | long values[nr_cpus]; |
86 | __u64 max_cnt = 0; | |
87 | __u64 cnt[SLOTS]; | |
88 | __u64 value; | |
89 | __u32 key; | |
90 | int i; | |
5c7fc2d2 AS |
91 | |
92 | for (key = 0; key < SLOTS; key++) { | |
d40fc181 | 93 | bpf_map_lookup_elem(fd, &key, values); |
5c7fc2d2 | 94 | value = 0; |
3059303f AS |
95 | for (i = 0; i < nr_cpus; i++) |
96 | value += values[i]; | |
5c7fc2d2 AS |
97 | cnt[key] = value; |
98 | total_events += value; | |
99 | if (value > max_cnt) | |
100 | max_cnt = value; | |
101 | } | |
102 | clear_stats(fd); | |
103 | for (key = full_range ? 0 : 29; key < SLOTS; key++) { | |
104 | int c = num_colors * cnt[key] / (max_cnt + 1); | |
105 | ||
106 | if (text_only) | |
107 | printf("%s", sym[c]); | |
108 | else | |
109 | printf("%s %s", color[c], nocolor); | |
110 | } | |
111 | printf(" # %lld\n", total_events); | |
112 | } | |
113 | ||
114 | int main(int ac, char **argv) | |
115 | { | |
55de1703 | 116 | struct rlimit r = {1024*1024, RLIM_INFINITY}; |
5c7fc2d2 AS |
117 | char filename[256]; |
118 | int i; | |
119 | ||
120 | snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); | |
121 | ||
55de1703 JDB |
122 | if (setrlimit(RLIMIT_MEMLOCK, &r)) { |
123 | perror("setrlimit(RLIMIT_MEMLOCK)"); | |
124 | return 1; | |
125 | } | |
126 | ||
5c7fc2d2 AS |
127 | if (load_bpf_file(filename)) { |
128 | printf("%s", bpf_log_buf); | |
129 | return 1; | |
130 | } | |
131 | ||
132 | for (i = 1; i < ac; i++) { | |
133 | if (strcmp(argv[i], "-a") == 0) { | |
134 | full_range = true; | |
135 | } else if (strcmp(argv[i], "-t") == 0) { | |
136 | text_only = true; | |
137 | } else if (strcmp(argv[i], "-h") == 0) { | |
138 | printf("Usage:\n" | |
139 | " -a display wider latency range\n" | |
140 | " -t text only\n"); | |
141 | return 1; | |
142 | } | |
143 | } | |
144 | ||
145 | printf(" heatmap of IO latency\n"); | |
146 | if (text_only) | |
147 | printf(" %s", sym[num_colors - 1]); | |
148 | else | |
149 | printf(" %s %s", color[num_colors - 1], nocolor); | |
150 | printf(" - many events with this latency\n"); | |
151 | ||
152 | if (text_only) | |
153 | printf(" %s", sym[0]); | |
154 | else | |
155 | printf(" %s %s", color[0], nocolor); | |
156 | printf(" - few events\n"); | |
157 | ||
158 | for (i = 0; ; i++) { | |
159 | if (i % 20 == 0) | |
160 | print_banner(); | |
161 | print_hist(map_fd[1]); | |
162 | sleep(2); | |
163 | } | |
164 | ||
165 | return 0; | |
166 | } |