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> 14 #include "libbpf.h" 15 #include "bpf_load.h" 16 17 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) 18 19 #define SLOTS 100 20 21 static void clear_stats(int fd) 22 { 23 unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); 24 __u64 values[nr_cpus]; 25 __u32 key; 26 27 memset(values, 0, sizeof(values)); 28 for (key = 0; key < SLOTS; key++) 29 bpf_update_elem(fd, &key, values, BPF_ANY); 30 } 31 32 const char *color[] = { 33 "\033[48;5;255m", 34 "\033[48;5;252m", 35 "\033[48;5;250m", 36 "\033[48;5;248m", 37 "\033[48;5;246m", 38 "\033[48;5;244m", 39 "\033[48;5;242m", 40 "\033[48;5;240m", 41 "\033[48;5;238m", 42 "\033[48;5;236m", 43 "\033[48;5;234m", 44 "\033[48;5;232m", 45 }; 46 const int num_colors = ARRAY_SIZE(color); 47 48 const char nocolor[] = "\033[00m"; 49 50 const char *sym[] = { 51 " ", 52 " ", 53 ".", 54 ".", 55 "*", 56 "*", 57 "o", 58 "o", 59 "O", 60 "O", 61 "#", 62 "#", 63 }; 64 65 bool full_range = false; 66 bool text_only = false; 67 68 static void print_banner(void) 69 { 70 if (full_range) 71 printf("|1ns |10ns |100ns |1us |10us |100us" 72 " |1ms |10ms |100ms |1s |10s\n"); 73 else 74 printf("|1us |10us |100us |1ms |10ms " 75 "|100ms |1s |10s\n"); 76 } 77 78 static void print_hist(int fd) 79 { 80 unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); 81 __u64 total_events = 0; 82 long values[nr_cpus]; 83 __u64 max_cnt = 0; 84 __u64 cnt[SLOTS]; 85 __u64 value; 86 __u32 key; 87 int i; 88 89 for (key = 0; key < SLOTS; key++) { 90 bpf_lookup_elem(fd, &key, values); 91 value = 0; 92 for (i = 0; i < nr_cpus; i++) 93 value += values[i]; 94 cnt[key] = value; 95 total_events += value; 96 if (value > max_cnt) 97 max_cnt = value; 98 } 99 clear_stats(fd); 100 for (key = full_range ? 0 : 29; key < SLOTS; key++) { 101 int c = num_colors * cnt[key] / (max_cnt + 1); 102 103 if (text_only) 104 printf("%s", sym[c]); 105 else 106 printf("%s %s", color[c], nocolor); 107 } 108 printf(" # %lld\n", total_events); 109 } 110 111 int main(int ac, char **argv) 112 { 113 char filename[256]; 114 int i; 115 116 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 117 118 if (load_bpf_file(filename)) { 119 printf("%s", bpf_log_buf); 120 return 1; 121 } 122 123 for (i = 1; i < ac; i++) { 124 if (strcmp(argv[i], "-a") == 0) { 125 full_range = true; 126 } else if (strcmp(argv[i], "-t") == 0) { 127 text_only = true; 128 } else if (strcmp(argv[i], "-h") == 0) { 129 printf("Usage:\n" 130 " -a display wider latency range\n" 131 " -t text only\n"); 132 return 1; 133 } 134 } 135 136 printf(" heatmap of IO latency\n"); 137 if (text_only) 138 printf(" %s", sym[num_colors - 1]); 139 else 140 printf(" %s %s", color[num_colors - 1], nocolor); 141 printf(" - many events with this latency\n"); 142 143 if (text_only) 144 printf(" %s", sym[0]); 145 else 146 printf(" %s %s", color[0], nocolor); 147 printf(" - few events\n"); 148 149 for (i = 0; ; i++) { 150 if (i % 20 == 0) 151 print_banner(); 152 print_hist(map_fd[1]); 153 sleep(2); 154 } 155 156 return 0; 157 } 158