1 #include <stdio.h> 2 #include <assert.h> 3 #include <limits.h> 4 #include "ffsb_stats.h" 5 #include "util.h" 6 7 char *syscall_names[] = { 8 "open", 9 "read", 10 "write", 11 "create", 12 "lseek", 13 "unlink", 14 "close", 15 "stat", 16 }; 17 18 /* yuck, just for the parser anyway.. */ 19 int ffsb_stats_str2syscall(char *str, syscall_t * sys) 20 { 21 int i; 22 int ret; 23 for (i = 0; i < FFSB_NUM_SYSCALLS; i++) { 24 ret = strncasecmp(syscall_names[i], str, 25 strlen(syscall_names[i])); 26 /* printf("%s = syscall_names[%d] vs %str ret = %d\n", 27 * syscall_names[i],i,str,ret); 28 */ 29 if (0 == ret) { 30 *sys = (syscall_t) i; /* ewww */ 31 /* printf("matched syscall %s\n",syscall_names[i]); */ 32 return 1; 33 } 34 } 35 printf("warning: failed to get match for syscall %s\n", str); 36 return 0; 37 } 38 39 void ffsb_statsc_init(ffsb_statsc_t * fsc) 40 { 41 fsc->num_buckets = 0; 42 fsc->buckets = NULL; 43 fsc->ignore_stats = 0; 44 } 45 46 void ffsb_statsc_addbucket(ffsb_statsc_t * fsc, uint32_t min, uint32_t max) 47 { 48 struct stat_bucket *temp; 49 fsc->num_buckets++; 50 51 /* printf("ffsb_realloc(): fsc_buckets = %d\n",fsc->num_buckets); */ 52 temp = ffsb_realloc(fsc->buckets, sizeof(struct stat_bucket) * 53 fsc->num_buckets); 54 55 fsc->buckets = temp; 56 57 /* Convert to micro-secs from milli-secs */ 58 fsc->buckets[fsc->num_buckets - 1].min = min; 59 fsc->buckets[fsc->num_buckets - 1].max = max; 60 } 61 62 void ffsb_statsc_destroy(ffsb_statsc_t * fsc) 63 { 64 free(fsc->buckets); 65 } 66 67 void ffsb_statsc_ignore_sys(ffsb_statsc_t * fsc, syscall_t s) 68 { 69 /* printf("fsis: oring 0x%x with 0x%x\n", 70 * fsc->ignore_stats, 71 * (1 << s ) ); 72 */ 73 fsc->ignore_stats |= (1 << s); 74 } 75 76 int fsc_ignore_sys(ffsb_statsc_t * fsc, syscall_t s) 77 { 78 return fsc->ignore_stats & (1 << s); 79 } 80 81 void ffsb_statsd_init(ffsb_statsd_t * fsd, ffsb_statsc_t * fsc) 82 { 83 int i; 84 memset(fsd, 0, sizeof(*fsd)); 85 86 for (i = 0; i < FFSB_NUM_SYSCALLS; i++) { 87 fsd->totals[i] = 0; 88 fsd->mins[i] = UINT_MAX; 89 fsd->maxs[i] = 0; 90 fsd->buckets[i] = ffsb_malloc(sizeof(uint32_t) * 91 fsc->num_buckets); 92 assert(fsd->buckets[i] != NULL); 93 94 memset(fsd->buckets[i], 0, sizeof(uint32_t) * fsc->num_buckets); 95 } 96 fsd->config = fsc; 97 } 98 99 void ffsb_statsd_destroy(ffsb_statsd_t * fsd) 100 { 101 int i; 102 for (i = 0; i < FFSB_NUM_SYSCALLS; i++) 103 free(fsd->buckets[i]); 104 } 105 106 void ffsb_add_data(ffsb_statsd_t * fsd, syscall_t s, uint32_t value) 107 { 108 unsigned num_buckets, i; 109 struct stat_bucket *bucket_defs; 110 111 if (!fsd || fsc_ignore_sys(fsd->config, s)) 112 return; 113 114 if (value < fsd->mins[s]) 115 fsd->mins[s] = value; 116 if (value > fsd->maxs[s]) 117 fsd->maxs[s] = value; 118 119 fsd->counts[s]++; 120 fsd->totals[s] += value; 121 122 if (fsd->config->num_buckets == 0) 123 return; 124 125 num_buckets = fsd->config->num_buckets; 126 bucket_defs = fsd->config->buckets; 127 128 for (i = 0; i < num_buckets; i++) { 129 struct stat_bucket *b = &bucket_defs[i]; 130 131 if (value <= b->max && value >= b->min) { 132 fsd->buckets[s][i]++; 133 break; 134 } 135 } 136 } 137 138 void ffsb_statsc_copy(ffsb_statsc_t * dest, ffsb_statsc_t * src) 139 { 140 memcpy(dest, src, sizeof(*src)); 141 } 142 143 void ffsb_statsd_add(ffsb_statsd_t * dest, ffsb_statsd_t * src) 144 { 145 int i, j; 146 unsigned num_buckets; 147 if (dest->config != src->config) 148 printf("ffsb_statsd_add: warning configs do not" 149 "match for data being collected\n"); 150 151 num_buckets = dest->config->num_buckets; 152 153 for (i = 0; i < FFSB_NUM_SYSCALLS; i++) { 154 dest->counts[i] += src->counts[i]; 155 dest->totals[i] += src->totals[i]; 156 157 if (src->mins[i] < dest->mins[i]) 158 dest->mins[i] = src->mins[i]; 159 if (src->maxs[i] > dest->maxs[i]) 160 dest->maxs[i] = src->maxs[i]; 161 162 for (j = 0; j < num_buckets; j++) 163 dest->buckets[i][j] += src->buckets[i][j]; 164 } 165 } 166 167 static void print_buckets_helper(ffsb_statsc_t * fsc, uint32_t * buckets) 168 { 169 int i; 170 if (fsc->num_buckets == 0) { 171 printf(" -\n"); 172 return; 173 } 174 for (i = 0; i < fsc->num_buckets; i++) { 175 struct stat_bucket *sb = &fsc->buckets[i]; 176 printf("\t\t msec_range[%d]\t%f - %f : %8u\n", 177 i, (double)sb->min / 1000.0f, (double)sb->max / 1000.0f, 178 buckets[i]); 179 } 180 printf("\n"); 181 } 182 183 void ffsb_statsd_print(ffsb_statsd_t * fsd) 184 { 185 int i; 186 printf("\nSystem Call Latency statistics in millisecs\n" "=====\n"); 187 printf("\t\tMin\t\tAvg\t\tMax\t\tTotal Calls\n"); 188 printf("\t\t========\t========\t========\t============\n"); 189 for (i = 0; i < FFSB_NUM_SYSCALLS; i++) 190 if (fsd->counts[i]) { 191 printf("[%7s]\t%05f\t%05lf\t%05f\t%12u\n", 192 syscall_names[i], (float)fsd->mins[i] / 1000.0f, 193 (fsd->totals[i] / (1000.0f * 194 (double)fsd->counts[i])), 195 (float)fsd->maxs[i] / 1000.0f, fsd->counts[i]); 196 print_buckets_helper(fsd->config, fsd->buckets[i]); 197 } 198 } 199 200 #if 0 /* Testing */ 201 202 void *ffsb_malloc(size_t s) 203 { 204 void *p = malloc(s); 205 assert(p != NULL); 206 return p; 207 } 208 209 int main(int arc, char *argv[]) 210 { 211 ffsb_statsc_t fsc; 212 ffsb_statsd_t fsd; 213 int i; 214 215 printf("init\n"); 216 217 ffsb_statsc_init(&fsc, 10); 218 ffsb_statsc_setbucket(&fsc, 0, 0.0f, 50.0f); 219 ffsb_statsc_setbucket(&fsc, 1, 50.0f, 10000.0f); 220 ffsb_statsc_setbucket(&fsc, 2, 0.1f, 0.2f); 221 ffsb_statsc_setbucket(&fsc, 3, 0.0f, 50.0f); 222 ffsb_statsc_setbucket(&fsc, 4, 50.0f, 10000.0f); 223 ffsb_statsc_setbucket(&fsc, 5, 0.1f, 0.2f); 224 ffsb_statsc_setbucket(&fsc, 6, 0.0f, 50.0f); 225 ffsb_statsc_setbucket(&fsc, 7, 50.0f, 10000.0f); 226 ffsb_statsc_setbucket(&fsc, 8, 0.1f, 0.2f); 227 ffsb_statsc_setbucket(&fsc, 9, 50.0f, 10000.0f); 228 ffsb_statsd_init(&fsd, &fsc); 229 230 printf("test\n"); 231 for (i = 0; i < 50000000; i++) 232 ffsb_add_data(&fsd, SYS_READ, (float)i); 233 234 printf("cleanup\n"); 235 ffsb_statsd_destroy(&fsd); 236 ffsb_statsc_destroy(&fsc); 237 return 0; 238 } 239 240 #endif /* Testing */ 241