[PATCH] btt: Fixed %utilization computation: idle not being computed right.
[blktrace.git] / btt / seek.c
CommitLineData
5225e788
AB
1/*
2 * blktrace output analysis: generate a timeline & gather statistics
3 *
4 * Copyright (C) 2006 Alan D. Brunelle <Alan.Brunelle@hp.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21#include "globals.h"
22
b2ecdd0f
ADB
23static struct file_info *all_files = NULL;
24
5225e788
AB
25struct seek_bkt {
26 long long sectors;
27 int nseeks;
28};
29
30struct seeki {
31 FILE *rfp, *wfp;
32 struct seek_bkt *seek_bkts;
33 int nseek_bkts;
34 long long total_seeks;
35 double total_sectors;
36 long long last_start, last_end;
37};
38
39FILE *seek_open(__u32 device, char rw)
40{
41 FILE *fp;
42 char *oname;
43 int mjr, mnr;
44
45 if (seek_name == NULL) return NULL;
46
47 mjr = device >> MINORBITS;
48 mnr = device & ((1 << MINORBITS) - 1);
49
b2ecdd0f 50 oname = malloc(strlen(seek_name)+32);
5225e788
AB
51 sprintf(oname, "%s_%03d,%03d_%c.dat", seek_name, mjr, mnr, rw);
52 if ((fp = fopen(oname, "w")) == NULL)
53 perror(oname);
b2ecdd0f
ADB
54 else
55 add_file(&all_files, fp, oname);
5225e788
AB
56
57 return fp;
58}
59
b2ecdd0f
ADB
60void seek_clean(void)
61{
62 clean_files(&all_files);
63}
64
5225e788
AB
65long long seek_dist(struct seeki *sip, struct io *iop)
66{
67 long long dist;
68 long long start = BIT_START(iop), end = BIT_END(iop);
69
70 /* Some overlap means no seek */
71 if (((sip->last_start <= start) && (start <= sip->last_end)) ||
72 ((sip->last_start <= end) && (end <= sip->last_end)))
73 dist = 0;
74 else if (start > sip->last_end)
75 dist = start - sip->last_end;
76 else
77 dist = start - sip->last_start;
78
79 sip->last_start = start;
80 sip->last_end = end;
81 return dist;
82}
83
84void *seeki_init(__u32 device)
85{
86 struct seeki *sip = malloc(sizeof(struct seeki));
87
88 sip->rfp = seek_open(device, 'r');
89 sip->wfp = seek_open(device, 'w');
90 sip->seek_bkts = NULL;
91 sip->nseek_bkts = 0;
92 sip->total_seeks = 0;
93 sip->total_sectors = 0.0;
94 sip->last_start = sip->last_end = 0;
95
96 return sip;
97}
98
99void seeki_add(void *handle, struct io *iop)
100{
101 int left, mid, right;
102 struct seek_bkt *bkt;
103 struct seeki *sip = handle;
104 long long dist = seek_dist(sip, iop);
105 FILE *fp = IOP_READ(iop) ? sip->rfp : sip->wfp;
106
107 if (fp)
108 fprintf(fp, "%15.9lf %13lld\n", BIT_TIME(iop->t.time), dist);
109
110 dist = llabs(dist);
111 sip->total_seeks++;
112 sip->total_sectors += dist;
113
114 left = 0;
115 right = sip->nseek_bkts-1;
116 while (left <= right) {
117 mid = (left+right)/2;
118 bkt = &sip->seek_bkts[mid];
119 if (dist == bkt->sectors) {
120 bkt->nseeks++;
121 return;
122 }
123
124 if (dist > bkt->sectors)
125 left = mid + 1;
126 else
127 right = mid - 1;
128 }
129
130 sip->seek_bkts = realloc(sip->seek_bkts,
131 (sip->nseek_bkts+1) * sizeof(struct seek_bkt));
132 if (sip->nseek_bkts > left)
133 memmove(&sip->seek_bkts[left+1], &sip->seek_bkts[left],
134 (sip->nseek_bkts - left) * sizeof(struct seek_bkt));
135 (bkt = &sip->seek_bkts[left])->sectors = dist;
136 bkt->nseeks = 1;
137 sip->nseek_bkts++;
138}
139
140long long seeki_nseeks(void *handle)
141{
142 return ((struct seeki *)handle)->total_seeks;
143}
144
145double seeki_mean(void *handle)
146{
147 struct seeki *sip = handle;
148 return sip->total_sectors / sip->total_seeks;
149}
150
151long long seeki_median(void *handle)
152{
153 int i;
154 struct seek_bkt *p;
155 struct seeki *sip = handle;
156 long long sofar = 0, target = sip->total_seeks / 2;
157
158 if (sip->total_seeks == 0) return 0;
159 for (i = 0, p = sip->seek_bkts; i < sip->nseek_bkts; i++, p++)
160 if ((sofar + p->nseeks) < target)
161 sofar += p->nseeks;
162 else
163 break;
164
165 return p->sectors;
166}
167
168int seeki_mode(void *handle, long long **modes_p, int *nseeks_p)
169{
170 int i;
171 struct seek_bkt *p;
172 int most_seeks = 0;
173 struct seeki *sip = handle;
174 int nmodes = 0;
175 long long *modes = NULL;
176
177 for (i = 0, p = sip->seek_bkts; i < sip->nseek_bkts; i++, p++)
178 if ((modes == NULL) || (p->nseeks > most_seeks)) {
179 most_seeks = p->nseeks;
180 modes = realloc(modes, sizeof(long long));
181 *modes = p->sectors;
182 nmodes = 1;
183 }
184 else if (p->nseeks == most_seeks) {
185 most_seeks = p->nseeks;
186 modes = realloc(modes, (nmodes+1) * sizeof(long long));
187 modes[nmodes++] = p->sectors;
188 }
189
190 *nseeks_p = most_seeks;
191 *modes_p = modes;
192 return nmodes;
193}