perfmonger 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +15 -0
  2. data/.dir-locals.el +2 -0
  3. data/.gitignore +4 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +12 -0
  6. data/COPYING +674 -0
  7. data/Gemfile +5 -0
  8. data/HOWTO.md +15 -0
  9. data/NEWS +115 -0
  10. data/README.md +61 -0
  11. data/Rakefile +8 -0
  12. data/bin/perfmonger +6 -0
  13. data/data/NOTICE +8 -0
  14. data/data/Twitter_Bootstrap_LICENSE.txt +176 -0
  15. data/data/assets/css/bootstrap-responsive.css +1109 -0
  16. data/data/assets/css/bootstrap.css +6167 -0
  17. data/data/assets/css/perfmonger.css +17 -0
  18. data/data/assets/dashboard.erb +319 -0
  19. data/data/assets/img/glyphicons-halflings-white.png +0 -0
  20. data/data/assets/img/glyphicons-halflings.png +0 -0
  21. data/data/assets/js/bootstrap.js +2280 -0
  22. data/data/assets/js/bootstrap.min.js +6 -0
  23. data/data/assets/js/canvasjs.js +9042 -0
  24. data/data/assets/js/canvasjs.min.js +271 -0
  25. data/data/sysstat.ioconf +268 -0
  26. data/ext/perfmonger/extconf.rb +19 -0
  27. data/ext/perfmonger/perfmonger.h +58 -0
  28. data/ext/perfmonger/perfmonger_record.c +754 -0
  29. data/ext/perfmonger/sysstat/common.c +627 -0
  30. data/ext/perfmonger/sysstat/common.h +207 -0
  31. data/ext/perfmonger/sysstat/ioconf.c +515 -0
  32. data/ext/perfmonger/sysstat/ioconf.h +84 -0
  33. data/ext/perfmonger/sysstat/iostat.c +1100 -0
  34. data/ext/perfmonger/sysstat/iostat.h +121 -0
  35. data/ext/perfmonger/sysstat/libsysstat.h +19 -0
  36. data/ext/perfmonger/sysstat/mpstat.c +953 -0
  37. data/ext/perfmonger/sysstat/mpstat.h +79 -0
  38. data/ext/perfmonger/sysstat/rd_stats.c +2388 -0
  39. data/ext/perfmonger/sysstat/rd_stats.h +651 -0
  40. data/ext/perfmonger/sysstat/sysconfig.h +13 -0
  41. data/lib/perfmonger/cli.rb +115 -0
  42. data/lib/perfmonger/command/base_command.rb +39 -0
  43. data/lib/perfmonger/command/fingerprint.rb +453 -0
  44. data/lib/perfmonger/command/plot.rb +429 -0
  45. data/lib/perfmonger/command/record.rb +32 -0
  46. data/lib/perfmonger/command/record_option.rb +149 -0
  47. data/lib/perfmonger/command/server.rb +294 -0
  48. data/lib/perfmonger/command/stat.rb +60 -0
  49. data/lib/perfmonger/command/stat_option.rb +29 -0
  50. data/lib/perfmonger/command/summary.rb +402 -0
  51. data/lib/perfmonger/config.rb +6 -0
  52. data/lib/perfmonger/version.rb +5 -0
  53. data/lib/perfmonger.rb +12 -0
  54. data/misc/release-howto.txt +17 -0
  55. data/misc/sample-cpu.png +0 -0
  56. data/misc/sample-read-iops.png +0 -0
  57. data/perfmonger.gemspec +44 -0
  58. data/test/run-test.sh +39 -0
  59. data/test/spec/bin_spec.rb +37 -0
  60. data/test/spec/data/2devices.expected +42 -0
  61. data/test/spec/data/2devices.output +42 -0
  62. data/test/spec/spec_helper.rb +20 -0
  63. data/test/spec/summary_spec.rb +193 -0
  64. data/test/test-perfmonger.c +145 -0
  65. data/test/test.h +9 -0
  66. metadata +154 -0
@@ -0,0 +1,627 @@
1
+ /*
2
+ * (C) 2011 Modified by Yuto HAYAMIZU (haya <at> tkl.iis.u-tokyo.ac.jp)
3
+ */
4
+
5
+ /*
6
+ * sar, sadc, sadf, mpstat and iostat common routines.
7
+ * (C) 1999-2010 by Sebastien GODARD (sysstat <at> orange.fr)
8
+ *
9
+ ***************************************************************************
10
+ * This program is free software; you can redistribute it and/or modify it *
11
+ * under the terms of the GNU General Public License as published by the *
12
+ * Free Software Foundation; either version 2 of the License, or (at your *
13
+ * option) any later version. *
14
+ * *
15
+ * This program is distributed in the hope that it will be useful, but *
16
+ * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY *
17
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
18
+ * for more details. *
19
+ * *
20
+ * You should have received a copy of the GNU General Public License along *
21
+ * with this program; if not, write to the Free Software Foundation, Inc., *
22
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
23
+ ***************************************************************************
24
+ */
25
+
26
+
27
+ #include <stdio.h>
28
+ #include <string.h>
29
+ #include <stdlib.h>
30
+ #include <time.h>
31
+ #include <errno.h>
32
+ #include <unistd.h> /* For STDOUT_FILENO, among others */
33
+ #include <sys/ioctl.h>
34
+ #include <sys/types.h>
35
+ #include <dirent.h>
36
+
37
+ #include "common.h"
38
+ #include "ioconf.h"
39
+ #include "rd_stats.h"
40
+
41
+ #ifdef USE_NLS
42
+ #include <locale.h>
43
+ #include <libintl.h>
44
+ #define _(string) gettext(string)
45
+ #else
46
+ #define _(string) (string)
47
+ #endif
48
+
49
+ /* Number of ticks per second */
50
+ unsigned int hz;
51
+ /* Number of bit shifts to convert pages to kB */
52
+ unsigned int kb_shift;
53
+
54
+ /*
55
+ ***************************************************************************
56
+ * Get local date and time.
57
+ *
58
+ * OUT:
59
+ * @rectime Current local date and time.
60
+ *
61
+ * RETURNS:
62
+ * Value of time in seconds since the Epoch.
63
+ ***************************************************************************
64
+ */
65
+ time_t get_localtime(struct tm *rectime)
66
+ {
67
+ time_t timer;
68
+ struct tm *ltm;
69
+
70
+ time(&timer);
71
+ ltm = localtime(&timer);
72
+
73
+ *rectime = *ltm;
74
+ return timer;
75
+ }
76
+
77
+ /*
78
+ ***************************************************************************
79
+ * Get date and time expressed in UTC.
80
+ *
81
+ * OUT:
82
+ * @rectime Current date and time expressed in UTC.
83
+ *
84
+ * RETURNS:
85
+ * Value of time in seconds since the Epoch.
86
+ ***************************************************************************
87
+ */
88
+ time_t get_gmtime(struct tm *rectime)
89
+ {
90
+ time_t timer;
91
+ struct tm *ltm;
92
+
93
+ time(&timer);
94
+ ltm = gmtime(&timer);
95
+
96
+ *rectime = *ltm;
97
+ return timer;
98
+ }
99
+
100
+ /*
101
+ ***************************************************************************
102
+ * Get date and time and take into account <ENV_TIME_DEFTM> variable.
103
+ *
104
+ * OUT:
105
+ * @rectime Current date and time.
106
+ *
107
+ * RETURNS:
108
+ * Value of time in seconds since the Epoch.
109
+ ***************************************************************************
110
+ */
111
+ time_t get_time(struct tm *rectime)
112
+ {
113
+ static int utc = 0;
114
+ char *e;
115
+
116
+ if (!utc) {
117
+ /* Read environment variable value once */
118
+ if ((e = getenv(ENV_TIME_DEFTM)) != NULL) {
119
+ utc = !strcmp(e, K_UTC);
120
+ }
121
+ utc++;
122
+ }
123
+
124
+ if (utc == 2)
125
+ return get_gmtime(rectime);
126
+ else
127
+ return get_localtime(rectime);
128
+ }
129
+
130
+ /*
131
+ ***************************************************************************
132
+ * Count number of comma-separated values in arguments list. For example,
133
+ * the number will be 3 for the list "foobar -p 1 -p 2,3,4 2 5".
134
+ *
135
+ * IN:
136
+ * @arg_c Number of arguments in the list.
137
+ * @arg_v Arguments list.
138
+ *
139
+ * RETURNS:
140
+ * Number of comma-separated values in the list.
141
+ ***************************************************************************
142
+ */
143
+ int count_csvalues(int arg_c, char **arg_v)
144
+ {
145
+ int opt = 1;
146
+ int nr = 0;
147
+ char *t;
148
+
149
+ while (opt < arg_c) {
150
+ if (strchr(arg_v[opt], ',')) {
151
+ for (t = arg_v[opt]; t; t = strchr(t + 1, ',')) {
152
+ nr++;
153
+ }
154
+ }
155
+ opt++;
156
+ }
157
+
158
+ return nr;
159
+ }
160
+
161
+ /*
162
+ ***************************************************************************
163
+ * Look for partitions of a given block device in /sys filesystem.
164
+ *
165
+ * IN:
166
+ * @dev_name Name of the block device.
167
+ *
168
+ * RETURNS:
169
+ * Number of partitions for the given block device.
170
+ ***************************************************************************
171
+ */
172
+ int get_dev_part_nr(char *dev_name)
173
+ {
174
+ DIR *dir;
175
+ struct dirent *drd;
176
+ char dfile[MAX_PF_NAME], line[MAX_PF_NAME];
177
+ int part = 0;
178
+
179
+ snprintf(dfile, MAX_PF_NAME, "%s/%s", SYSFS_BLOCK, dev_name);
180
+ dfile[MAX_PF_NAME - 1] = '\0';
181
+
182
+ /* Open current device directory in /sys/block */
183
+ if ((dir = opendir(dfile)) == NULL)
184
+ return 0;
185
+
186
+ /* Get current file entry */
187
+ while ((drd = readdir(dir)) != NULL) {
188
+ if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, ".."))
189
+ continue;
190
+ snprintf(line, MAX_PF_NAME, "%s/%s/%s", dfile, drd->d_name, S_STAT);
191
+ line[MAX_PF_NAME - 1] = '\0';
192
+
193
+ /* Try to guess if current entry is a directory containing a stat file */
194
+ if (!access(line, R_OK)) {
195
+ /* Yep... */
196
+ part++;
197
+ }
198
+ }
199
+
200
+ /* Close directory */
201
+ closedir(dir);
202
+
203
+ return part;
204
+ }
205
+
206
+ /*
207
+ ***************************************************************************
208
+ * Look for block devices present in /sys/ filesystem:
209
+ * Check first that sysfs is mounted (done by trying to open /sys/block
210
+ * directory), then find number of devices registered.
211
+ *
212
+ * IN:
213
+ * @display_partitions Set to TRUE if partitions must also be counted.
214
+ *
215
+ * RETURNS:
216
+ * Total number of block devices (and partitions if @display_partitions was
217
+ * set).
218
+ ***************************************************************************
219
+ */
220
+ int get_sysfs_dev_nr(int display_partitions)
221
+ {
222
+ DIR *dir;
223
+ struct dirent *drd;
224
+ char line[MAX_PF_NAME];
225
+ int dev = 0;
226
+
227
+ /* Open /sys/block directory */
228
+ if ((dir = opendir(SYSFS_BLOCK)) == NULL)
229
+ /* sysfs not mounted, or perhaps this is an old kernel */
230
+ return 0;
231
+
232
+ /* Get current file entry in /sys/block directory */
233
+ while ((drd = readdir(dir)) != NULL) {
234
+ if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, ".."))
235
+ continue;
236
+ snprintf(line, MAX_PF_NAME, "%s/%s/%s", SYSFS_BLOCK, drd->d_name, S_STAT);
237
+ line[MAX_PF_NAME - 1] = '\0';
238
+
239
+ /* Try to guess if current entry is a directory containing a stat file */
240
+ if (!access(line, R_OK)) {
241
+ /* Yep... */
242
+ dev++;
243
+
244
+ if (display_partitions) {
245
+ /* We also want the number of partitions for this device */
246
+ dev += get_dev_part_nr(drd->d_name);
247
+ }
248
+ }
249
+ }
250
+
251
+ /* Close /sys/block directory */
252
+ closedir(dir);
253
+
254
+ return dev;
255
+ }
256
+
257
+ /*
258
+ ***************************************************************************
259
+ * Read /proc/devices file and get device-mapper major number.
260
+ * If device-mapper entry is not found in file, use DEFAULT_DEMAP_MAJOR
261
+ * number.
262
+ *
263
+ * RETURNS:
264
+ * Device-mapper major number.
265
+ ***************************************************************************
266
+ */
267
+ unsigned int get_devmap_major(void)
268
+ {
269
+ FILE *fp;
270
+ char line[128];
271
+ unsigned int dm_major = DEFAULT_DEVMAP_MAJOR;
272
+
273
+ if ((fp = fopen(DEVICES, "r")) == NULL)
274
+ return dm_major;
275
+
276
+ while (fgets(line, 128, fp) != NULL) {
277
+
278
+ if (strstr(line, "device-mapper")) {
279
+ /* Read device-mapper major number */
280
+ sscanf(line, "%u", &dm_major);
281
+ }
282
+ }
283
+
284
+ fclose(fp);
285
+
286
+ return dm_major;
287
+ }
288
+
289
+ /*
290
+ ***************************************************************************
291
+ * Print banner.
292
+ *
293
+ * IN:
294
+ * @rectime Date and time to display.
295
+ * @sysname System name to display.
296
+ * @release System release number to display.
297
+ * @nodename Hostname to display.
298
+ * @machine Machine architecture to display.
299
+ * @cpu_nr Number of CPU.
300
+ *
301
+ * RETURNS:
302
+ * TRUE if S_TIME_FORMAT is set to ISO, or FALSE otherwise.
303
+ ***************************************************************************
304
+ */
305
+ int print_gal_header(struct tm *rectime, char *sysname, char *release,
306
+ char *nodename, char *machine, int cpu_nr)
307
+ {
308
+ char cur_date[64];
309
+ char *e;
310
+ int rc = 0;
311
+
312
+ if (rectime == NULL) {
313
+ strcpy(cur_date, "?/?/?");
314
+ }
315
+ else if (((e = getenv(ENV_TIME_FMT)) != NULL) && !strcmp(e, K_ISO)) {
316
+ strftime(cur_date, sizeof(cur_date), "%Y-%m-%d", rectime);
317
+ rc = 1;
318
+ }
319
+ else {
320
+ strftime(cur_date, sizeof(cur_date), "%x", rectime);
321
+ }
322
+
323
+ printf("%s %s (%s) \t%s \t_%s_\t(%d CPU)\n", sysname, release, nodename,
324
+ cur_date, machine, cpu_nr);
325
+
326
+ return rc;
327
+ }
328
+
329
+ #ifdef USE_NLS
330
+ /*
331
+ ***************************************************************************
332
+ * Init National Language Support.
333
+ ***************************************************************************
334
+ */
335
+ void init_nls(void)
336
+ {
337
+ setlocale(LC_MESSAGES, "");
338
+ setlocale(LC_CTYPE, "");
339
+ setlocale(LC_TIME, "");
340
+ setlocale(LC_NUMERIC, "");
341
+
342
+ bindtextdomain(PACKAGE, LOCALEDIR);
343
+ textdomain(PACKAGE);
344
+ }
345
+ #endif
346
+
347
+ /*
348
+ ***************************************************************************
349
+ * Get number of rows for current window.
350
+ *
351
+ * RETURNS:
352
+ * Number of rows.
353
+ ***************************************************************************
354
+ */
355
+ int get_win_height(void)
356
+ {
357
+ struct winsize win;
358
+ /*
359
+ * This default value will be used whenever STDOUT
360
+ * is redirected to a pipe or a file
361
+ */
362
+ int rows = 3600 * 24;
363
+
364
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1) {
365
+ if (win.ws_row > 2) {
366
+ rows = win.ws_row - 2;
367
+ }
368
+ }
369
+ return rows;
370
+ }
371
+
372
+ /*
373
+ ***************************************************************************
374
+ * Remove /dev from path name.
375
+ *
376
+ * IN:
377
+ * @name Device name (may begins with "/dev/")
378
+ *
379
+ * RETURNS:
380
+ * Device basename.
381
+ ***************************************************************************
382
+ */
383
+ char *device_name(char *name)
384
+ {
385
+ if (!strncmp(name, "/dev/", 5))
386
+ return name + 5;
387
+
388
+ return name;
389
+ }
390
+
391
+ /*
392
+ ***************************************************************************
393
+ * Test whether given name is a device or a partition, using sysfs.
394
+ * This is more straightforward that using ioc_iswhole() function from
395
+ * ioconf.c which should be used only with kernels that don't have sysfs.
396
+ *
397
+ * IN:
398
+ * @name Device or partition name.
399
+ *
400
+ * RETURNS:
401
+ * TRUE if @name is a (whole) device.
402
+ ***************************************************************************
403
+ */
404
+ int is_device(char *name)
405
+ {
406
+ char syspath[PATH_MAX];
407
+ char *slash;
408
+
409
+ /* Some devices may have a slash in their name (eg. cciss/c0d0...) */
410
+ while ((slash = strchr(name, '/'))) {
411
+ *slash = '!';
412
+ }
413
+ snprintf(syspath, sizeof(syspath), "%s/%s", SYSFS_BLOCK, name);
414
+
415
+ return !(access(syspath, F_OK));
416
+ }
417
+
418
+ /*
419
+ ***************************************************************************
420
+ * Get page shift in kB.
421
+ ***************************************************************************
422
+ */
423
+ void get_kb_shift(void)
424
+ {
425
+ int shift = 0;
426
+ long size;
427
+
428
+ /* One can also use getpagesize() to get the size of a page */
429
+ if ((size = sysconf(_SC_PAGESIZE)) == -1) {
430
+ perror("sysconf");
431
+ }
432
+
433
+ size >>= 10; /* Assume that a page has a minimum size of 1 kB */
434
+
435
+ while (size > 1) {
436
+ shift++;
437
+ size >>= 1;
438
+ }
439
+
440
+ kb_shift = (unsigned int) shift;
441
+ }
442
+
443
+ /*
444
+ ***************************************************************************
445
+ * Get number of clock ticks per second.
446
+ ***************************************************************************
447
+ */
448
+ void get_HZ(void)
449
+ {
450
+ long ticks;
451
+
452
+ if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
453
+ perror("sysconf");
454
+ }
455
+
456
+ hz = (unsigned int) ticks;
457
+ }
458
+
459
+ /*
460
+ ***************************************************************************
461
+ * Handle overflow conditions properly for counters which are read as
462
+ * unsigned long long, but which can be unsigned long long or
463
+ * unsigned long only depending on the kernel version used.
464
+ * @value1 and @value2 being two values successively read for this
465
+ * counter, if @value2 < @value1 and @value1 <= 0xffffffff, then we can
466
+ * assume that the counter's type was unsigned long and has overflown, and
467
+ * so the difference @value2 - @value1 must be casted to this type.
468
+ * NOTE: These functions should no longer be necessary to handle a particular
469
+ * stat counter when we can assume that everybody is using a recent kernel
470
+ * (defining this counter as unsigned long long).
471
+ ***************************************************************************
472
+ */
473
+ double ll_sp_value(unsigned long long value1, unsigned long long value2,
474
+ unsigned long long itv)
475
+ {
476
+ if ((value2 < value1) && (value1 <= 0xffffffff))
477
+ /* Counter's type was unsigned long and has overflown */
478
+ return ((double) ((value2 - value1) & 0xffffffff)) / itv * 100;
479
+ else
480
+ return SP_VALUE(value1, value2, itv);
481
+ }
482
+
483
+ double ll_s_value(unsigned long long value1, unsigned long long value2,
484
+ unsigned long long itv)
485
+ {
486
+ if ((value2 < value1) && (value1 <= 0xffffffff))
487
+ /* Counter's type was unsigned long and has overflown */
488
+ return ((double) ((value2 - value1) & 0xffffffff)) / itv * HZ;
489
+ else
490
+ return S_VALUE(value1, value2, itv);
491
+ }
492
+
493
+ /*
494
+ ***************************************************************************
495
+ * Compute time interval.
496
+ *
497
+ * IN:
498
+ * @prev_uptime Previous uptime value in jiffies.
499
+ * @curr_uptime Current uptime value in jiffies.
500
+ *
501
+ * RETURNS:
502
+ * Interval of time in jiffies.
503
+ ***************************************************************************
504
+ */
505
+ unsigned long long get_interval(unsigned long long prev_uptime,
506
+ unsigned long long curr_uptime)
507
+ {
508
+ unsigned long long itv;
509
+
510
+ /* prev_time=0 when displaying stats since system startup */
511
+ itv = curr_uptime - prev_uptime;
512
+
513
+ if (!itv) { /* Paranoia checking */
514
+ itv = 1;
515
+ }
516
+
517
+ return itv;
518
+ }
519
+
520
+ /*
521
+ ***************************************************************************
522
+ * Since ticks may vary slightly from CPU to CPU, we'll want
523
+ * to recalculate itv based on this CPU's tick count, rather
524
+ * than that reported by the "cpu" line. Otherwise we
525
+ * occasionally end up with slightly skewed figures, with
526
+ * the skew being greater as the time interval grows shorter.
527
+ *
528
+ * IN:
529
+ * @scc Current sample statistics for current CPU.
530
+ * @scp Previous sample statistics for current CPU.
531
+ *
532
+ * RETURNS:
533
+ * Interval of time based on current CPU.
534
+ ***************************************************************************
535
+ */
536
+ unsigned long long get_per_cpu_interval(struct stats_cpu *scc,
537
+ struct stats_cpu *scp)
538
+ {
539
+ /* Don't take cpu_guest into account because cpu_user already includes it */
540
+ return ((scc->cpu_user + scc->cpu_nice +
541
+ scc->cpu_sys + scc->cpu_iowait +
542
+ scc->cpu_idle + scc->cpu_steal +
543
+ scc->cpu_hardirq + scc->cpu_softirq) -
544
+ (scp->cpu_user + scp->cpu_nice +
545
+ scp->cpu_sys + scp->cpu_iowait +
546
+ scp->cpu_idle + scp->cpu_steal +
547
+ scp->cpu_hardirq + scp->cpu_softirq));
548
+ }
549
+
550
+ /*
551
+ ***************************************************************************
552
+ * Unhandled situation: Panic and exit.
553
+ *
554
+ * IN:
555
+ * @function Function name where situation occured.
556
+ * @error_code Error code.
557
+ ***************************************************************************
558
+ */
559
+ void sysstat_panic(const char *function, int error_code)
560
+ {
561
+ fprintf(stderr, "sysstat: %s[%d]: Last chance handler...\n",
562
+ function, error_code);
563
+ exit(1);
564
+ }
565
+
566
+ /*
567
+ ***************************************************************************
568
+ * Count number of bits set in an array.
569
+ *
570
+ * IN:
571
+ * @ptr Pointer to array.
572
+ * @size Size of array in bytes.
573
+ *
574
+ * RETURNS:
575
+ * Number of bits set in the array.
576
+ ***************************************************************************
577
+ */
578
+ int count_bits(void *ptr, int size)
579
+ {
580
+ int nr = 0, i, k;
581
+ char *p;
582
+
583
+ p = ptr;
584
+ for (i = 0; i < size; i++, p++) {
585
+ k = 0x80;
586
+ while (k) {
587
+ if (*p & k)
588
+ nr++;
589
+ k >>= 1;
590
+ }
591
+ }
592
+
593
+ return nr;
594
+ }
595
+
596
+ /*
597
+ ***************************************************************************
598
+ * Compute "extended" device statistics (service time, etc.).
599
+ *
600
+ * IN:
601
+ * @sdc Structure with current device statistics.
602
+ * @sdp Structure with previous device statistics.
603
+ * @itv Interval of time in jiffies.
604
+ *
605
+ * OUT:
606
+ * @xds Structure with extended statistics.
607
+ ***************************************************************************
608
+ */
609
+ void compute_ext_disk_stats(struct stats_disk *sdc, struct stats_disk *sdp,
610
+ unsigned long long itv, struct ext_disk_stats *xds)
611
+ {
612
+ double tput
613
+ = ((double) (sdc->nr_ios - sdp->nr_ios)) * HZ / itv;
614
+
615
+ xds->util = S_VALUE(sdp->tot_ticks, sdc->tot_ticks, itv);
616
+ xds->svctm = tput ? xds->util / tput : 0.0;
617
+ /*
618
+ * Kernel gives ticks already in milliseconds for all platforms
619
+ * => no need for further scaling.
620
+ */
621
+ xds->await = (sdc->nr_ios - sdp->nr_ios) ?
622
+ ((sdc->rd_ticks - sdp->rd_ticks) + (sdc->wr_ticks - sdp->wr_ticks)) /
623
+ ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0;
624
+ xds->arqsz = (sdc->nr_ios - sdp->nr_ios) ?
625
+ ((sdc->rd_sect - sdp->rd_sect) + (sdc->wr_sect - sdp->wr_sect)) /
626
+ ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0;
627
+ }