0001
0002
0003
0004 #include <stdio.h>
0005 #include <stdlib.h>
0006 #include <signal.h>
0007 #include <unistd.h>
0008 #include <stdbool.h>
0009 #include <string.h>
0010
0011 #include <bpf/bpf.h>
0012 #include <bpf/libbpf.h>
0013 #include "bpf_util.h"
0014
0015 #define SLOTS 100
0016
0017 static void clear_stats(int fd)
0018 {
0019 unsigned int nr_cpus = bpf_num_possible_cpus();
0020 __u64 values[nr_cpus];
0021 __u32 key;
0022
0023 memset(values, 0, sizeof(values));
0024 for (key = 0; key < SLOTS; key++)
0025 bpf_map_update_elem(fd, &key, values, BPF_ANY);
0026 }
0027
0028 const char *color[] = {
0029 "\033[48;5;255m",
0030 "\033[48;5;252m",
0031 "\033[48;5;250m",
0032 "\033[48;5;248m",
0033 "\033[48;5;246m",
0034 "\033[48;5;244m",
0035 "\033[48;5;242m",
0036 "\033[48;5;240m",
0037 "\033[48;5;238m",
0038 "\033[48;5;236m",
0039 "\033[48;5;234m",
0040 "\033[48;5;232m",
0041 };
0042 const int num_colors = ARRAY_SIZE(color);
0043
0044 const char nocolor[] = "\033[00m";
0045
0046 const char *sym[] = {
0047 " ",
0048 " ",
0049 ".",
0050 ".",
0051 "*",
0052 "*",
0053 "o",
0054 "o",
0055 "O",
0056 "O",
0057 "#",
0058 "#",
0059 };
0060
0061 bool full_range = false;
0062 bool text_only = false;
0063
0064 static void print_banner(void)
0065 {
0066 if (full_range)
0067 printf("|1ns |10ns |100ns |1us |10us |100us"
0068 " |1ms |10ms |100ms |1s |10s\n");
0069 else
0070 printf("|1us |10us |100us |1ms |10ms "
0071 "|100ms |1s |10s\n");
0072 }
0073
0074 static void print_hist(int fd)
0075 {
0076 unsigned int nr_cpus = bpf_num_possible_cpus();
0077 __u64 total_events = 0;
0078 long values[nr_cpus];
0079 __u64 max_cnt = 0;
0080 __u64 cnt[SLOTS];
0081 __u64 value;
0082 __u32 key;
0083 int i;
0084
0085 for (key = 0; key < SLOTS; key++) {
0086 bpf_map_lookup_elem(fd, &key, values);
0087 value = 0;
0088 for (i = 0; i < nr_cpus; i++)
0089 value += values[i];
0090 cnt[key] = value;
0091 total_events += value;
0092 if (value > max_cnt)
0093 max_cnt = value;
0094 }
0095 clear_stats(fd);
0096 for (key = full_range ? 0 : 29; key < SLOTS; key++) {
0097 int c = num_colors * cnt[key] / (max_cnt + 1);
0098
0099 if (text_only)
0100 printf("%s", sym[c]);
0101 else
0102 printf("%s %s", color[c], nocolor);
0103 }
0104 printf(" # %lld\n", total_events);
0105 }
0106
0107 int main(int ac, char **argv)
0108 {
0109 struct bpf_link *links[2];
0110 struct bpf_program *prog;
0111 struct bpf_object *obj;
0112 char filename[256];
0113 int map_fd, i, j = 0;
0114
0115 for (i = 1; i < ac; i++) {
0116 if (strcmp(argv[i], "-a") == 0) {
0117 full_range = true;
0118 } else if (strcmp(argv[i], "-t") == 0) {
0119 text_only = true;
0120 } else if (strcmp(argv[i], "-h") == 0) {
0121 printf("Usage:\n"
0122 " -a display wider latency range\n"
0123 " -t text only\n");
0124 return 1;
0125 }
0126 }
0127
0128 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
0129 obj = bpf_object__open_file(filename, NULL);
0130 if (libbpf_get_error(obj)) {
0131 fprintf(stderr, "ERROR: opening BPF object file failed\n");
0132 return 0;
0133 }
0134
0135
0136 if (bpf_object__load(obj)) {
0137 fprintf(stderr, "ERROR: loading BPF object file failed\n");
0138 goto cleanup;
0139 }
0140
0141 map_fd = bpf_object__find_map_fd_by_name(obj, "lat_map");
0142 if (map_fd < 0) {
0143 fprintf(stderr, "ERROR: finding a map in obj file failed\n");
0144 goto cleanup;
0145 }
0146
0147 bpf_object__for_each_program(prog, obj) {
0148 links[j] = bpf_program__attach(prog);
0149 if (libbpf_get_error(links[j])) {
0150 fprintf(stderr, "ERROR: bpf_program__attach failed\n");
0151 links[j] = NULL;
0152 goto cleanup;
0153 }
0154 j++;
0155 }
0156
0157 printf(" heatmap of IO latency\n");
0158 if (text_only)
0159 printf(" %s", sym[num_colors - 1]);
0160 else
0161 printf(" %s %s", color[num_colors - 1], nocolor);
0162 printf(" - many events with this latency\n");
0163
0164 if (text_only)
0165 printf(" %s", sym[0]);
0166 else
0167 printf(" %s %s", color[0], nocolor);
0168 printf(" - few events\n");
0169
0170 for (i = 0; ; i++) {
0171 if (i % 20 == 0)
0172 print_banner();
0173 print_hist(map_fd);
0174 sleep(2);
0175 }
0176
0177 cleanup:
0178 for (j--; j >= 0; j--)
0179 bpf_link__destroy(links[j]);
0180
0181 bpf_object__close(obj);
0182 return 0;
0183 }