1 /* 2 * Copyright IBM Corp. 2008 3 * 4 * Author(s): Martin Peschke <mp3 (at) de.ibm.com> 5 * Stefan Raspl <stefan.raspl (at) de.ibm.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 #ifndef STATS_H 23 #define STATS_H 24 25 #include <linux/types.h> 26 #include "blktrace.h" 27 28 struct minmax { 29 __u64 min; 30 __u64 max; 31 __u64 sum; 32 __u64 sos; 33 __u64 num; 34 }; 35 36 static inline void minmax_init(struct minmax *mm) 37 { 38 mm->min = -1ULL; 39 mm->max = 0; 40 mm->sum = 0; 41 mm->sos = 0; 42 mm->num = 0; 43 } 44 45 static inline void minmax_account(struct minmax *mm, __u64 value) 46 { 47 mm->sum += value; 48 mm->sos += value * value; 49 if (value < mm->min) 50 mm->min = value; 51 if (value > mm->max) 52 mm->max = value; 53 mm->num++; 54 } 55 56 static inline void minmax_merge(struct minmax *dst, struct minmax *src) 57 { 58 dst->sum += src->sum; 59 dst->sos += src->sos; 60 if (src->min < dst->min) 61 dst->min = src->min; 62 if (src->max > dst->max) 63 dst->max = src->max; 64 dst->num += src->num; 65 } 66 67 static inline void minmax_to_be(struct minmax *mm) 68 { 69 mm->sum = cpu_to_be64(mm->sum); 70 mm->sos = cpu_to_be64(mm->sos); 71 mm->min = cpu_to_be64(mm->min); 72 mm->max = cpu_to_be64(mm->max); 73 mm->num = cpu_to_be64(mm->num); 74 } 75 76 static inline double minmax_avg(struct minmax *mm) 77 { 78 if (!mm->num) 79 return 0; 80 81 return (mm->sum / (double)mm->num); 82 } 83 84 static inline double minmax_var(struct minmax *mm) 85 { 86 double num = (double)mm->num; 87 88 if (!mm->num) 89 return 0; 90 91 return ((mm->sos - ((mm->sum * mm->sum) / num)) / num); 92 } 93 94 static inline int minmax_print(FILE *fp, const char *s, struct minmax *mm) 95 { 96 return fprintf(fp, "%s: num %Ld, min %Ld, max %Ld, sum %Ld, squ %Ld, " 97 "avg %.1f, var %.1f\n", s, (unsigned long long)mm->num, 98 (unsigned long long)mm->min, (unsigned long long)mm->max, 99 (unsigned long long)mm->sum, (unsigned long long)mm->sos, 100 minmax_avg(mm), minmax_var(mm)); 101 } 102 103 struct histlog2 { 104 int first; 105 int delta; 106 int num; 107 }; 108 109 static inline __u64 histlog2_upper_limit(int index, struct histlog2 *h) 110 { 111 return h->first + (index ? h->delta << (index - 1) : 0); 112 } 113 114 static inline int histlog2_index(__u64 val, struct histlog2 *h) 115 { 116 int i; 117 118 for (i = 0; i < (h->num - 1) && val > histlog2_upper_limit(i, h); i++); 119 return i; 120 } 121 122 static inline void histlog2_account(__u32 *bucket, __u32 val, 123 struct histlog2 *h) 124 { 125 int index = histlog2_index(val, h); 126 bucket[index]++; 127 } 128 129 static inline void histlog2_merge(struct histlog2 *h, __u32 *dst, __u32 *src) 130 { 131 int i; 132 133 for (i = 0; i < h->num; i++) 134 dst[i] += src[i]; 135 } 136 137 static inline void histlog2_to_be(__u32 a[], struct histlog2 *h) 138 { 139 int i; 140 141 for (i = 0; i < h->num; i++) 142 a[i] = cpu_to_be32(a[i]); 143 } 144 145 static inline void histlog2_print(FILE *fp, const char *s, __u32 a[], 146 struct histlog2 *h) 147 { 148 int i; 149 150 fprintf(fp, "%s:\n", s); 151 for (i = 0; i < h->num - 1; i++) { 152 fprintf(fp, " %10ld:%6d", 153 (unsigned long)(histlog2_upper_limit(i, h)), a[i]); 154 if (!((i + 1) % 4)) 155 fprintf(fp, "\n"); 156 } 157 fprintf(fp, " >%8ld:%6d\n", 158 (unsigned long)(histlog2_upper_limit(i - 1, h)), a[i]); 159 } 160 161 #endif 162