Print this page
patch relling-feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/stat/vmstat/vmstat.c
+++ new/usr/src/cmd/stat/vmstat/vmstat.c
1 1 /*
2 2 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
3 3 */
4 4
5 5 /*
6 6 * Copyright (c) 1980 Regents of the University of California.
7 7 * All rights reserved. The Berkeley software License Agreement
8 8 * specifies the terms and conditions for redistribution.
9 9 */
10 10
11 11 /* from UCB 5.4 5/17/86 */
12 12 /* from SunOS 4.1, SID 1.31 */
13 13
14 14 #include <stdio.h>
15 15 #include <stdlib.h>
16 16 #include <stdarg.h>
17 17 #include <ctype.h>
18 18 #include <unistd.h>
19 19 #include <memory.h>
20 20 #include <string.h>
21 21 #include <fcntl.h>
22 22 #include <errno.h>
23 23 #include <signal.h>
24 24 #include <values.h>
25 25 #include <poll.h>
26 26 #include <locale.h>
27 27
28 28 #include "statcommon.h"
29 29
30 30 char *cmdname = "vmstat";
31 31 int caught_cont = 0;
32 32
33 33 static uint_t timestamp_fmt = NODATE;
34 34
35 35 static int hz;
36 36 static int pagesize;
37 37 static double etime;
38 38 static int lines = 1;
39 39 static int swflag = 0, pflag = 0;
40 40 static int suppress_state;
41 41 static long iter = 0;
42 42 static hrtime_t period_n = 0;
43 43 static struct snapshot *ss;
44 44
45 45 struct iodev_filter df;
46 46
47 47 #define pgtok(a) ((a) * (pagesize >> 10))
48 48 #define denom(x) ((x) ? (x) : 1)
49 49 #define REPRINT 19
50 50
51 51 static void dovmstats(struct snapshot *old, struct snapshot *new);
52 52 static void printhdr(int);
53 53 static void dosum(struct sys_snapshot *ss);
54 54 static void dointr(struct snapshot *ss);
55 55 static void usage(void);
56 56
57 57 int
58 58 main(int argc, char **argv)
59 59 {
60 60 struct snapshot *old = NULL;
61 61 enum snapshot_types types = SNAP_SYSTEM;
62 62 int summary = 0;
63 63 int intr = 0;
64 64 kstat_ctl_t *kc;
65 65 int forever = 0;
66 66 hrtime_t start_n;
67 67 int c;
68 68
69 69 (void) setlocale(LC_ALL, "");
70 70 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
71 71 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
72 72 #endif
73 73 (void) textdomain(TEXT_DOMAIN);
74 74
75 75 pagesize = sysconf(_SC_PAGESIZE);
76 76 hz = sysconf(_SC_CLK_TCK);
77 77
78 78 while ((c = getopt(argc, argv, "ipqsST:")) != EOF)
79 79 switch (c) {
80 80 case 'S':
81 81 swflag = !swflag;
82 82 break;
83 83 case 's':
84 84 summary = 1;
85 85 break;
86 86 case 'i':
87 87 intr = 1;
88 88 break;
89 89 case 'q':
90 90 suppress_state = 1;
91 91 break;
92 92 case 'p':
93 93 pflag++; /* detailed paging info */
94 94 break;
95 95 case 'T':
96 96 if (optarg) {
97 97 if (*optarg == 'u')
98 98 timestamp_fmt = UDATE;
99 99 else if (*optarg == 'd')
100 100 timestamp_fmt = DDATE;
101 101 else
102 102 usage();
103 103 } else {
104 104 usage();
105 105 }
106 106 break;
107 107 default:
108 108 usage();
109 109 }
110 110
111 111 argc -= optind;
112 112 argv += optind;
113 113
114 114 /* consistency with iostat */
115 115 types |= SNAP_CPUS;
116 116
117 117 if (intr)
118 118 types |= SNAP_INTERRUPTS;
119 119 if (!intr)
120 120 types |= SNAP_IODEVS;
121 121
122 122 /* max to fit in less than 80 characters */
123 123 df.if_max_iodevs = 4;
124 124 df.if_allowed_types = IODEV_DISK;
125 125 df.if_nr_names = 0;
126 126 df.if_names = safe_alloc(df.if_max_iodevs * sizeof (char *));
127 127 (void) memset(df.if_names, 0, df.if_max_iodevs * sizeof (char *));
128 128
129 129 while (argc > 0 && !isdigit(argv[0][0]) &&
130 130 df.if_nr_names < df.if_max_iodevs) {
131 131 df.if_names[df.if_nr_names] = *argv;
132 132 df.if_nr_names++;
133 133 argc--, argv++;
134 134 }
135 135
136 136 kc = open_kstat();
137 137
138 138 start_n = gethrtime();
139 139
140 140 ss = acquire_snapshot(kc, types, &df);
141 141
142 142 /* time, in seconds, since boot */
143 143 etime = ss->s_sys.ss_ticks / hz;
144 144
145 145 if (intr) {
146 146 dointr(ss);
147 147 free_snapshot(ss);
148 148 exit(0);
149 149 }
150 150 if (summary) {
151 151 dosum(&ss->s_sys);
152 152 free_snapshot(ss);
153 153 exit(0);
154 154 }
155 155
156 156 if (argc > 0) {
157 157 long interval;
158 158 char *endptr;
159 159
160 160 errno = 0;
161 161 interval = strtol(argv[0], &endptr, 10);
162 162
163 163 if (errno > 0 || *endptr != '\0' || interval <= 0 ||
164 164 interval > MAXINT)
165 165 usage();
166 166 period_n = (hrtime_t)interval * NANOSEC;
167 167 if (period_n <= 0)
168 168 usage();
169 169 iter = MAXLONG;
170 170 if (argc > 1) {
171 171 iter = strtol(argv[1], NULL, 10);
172 172 if (errno > 0 || *endptr != '\0' || iter <= 0)
173 173 usage();
174 174 } else
175 175 forever = 1;
176 176 if (argc > 2)
177 177 usage();
178 178 }
179 179
180 180 (void) sigset(SIGCONT, printhdr);
181 181
182 182 dovmstats(old, ss);
183 183 while (forever || --iter > 0) {
184 184 /* (void) poll(NULL, 0, poll_interval); */
185 185
186 186 /* Have a kip */
187 187 sleep_until(&start_n, period_n, forever, &caught_cont);
188 188
189 189 free_snapshot(old);
190 190 old = ss;
191 191 ss = acquire_snapshot(kc, types, &df);
192 192
193 193 if (!suppress_state)
194 194 snapshot_report_changes(old, ss);
195 195
196 196 /* if config changed, show stats from boot */
197 197 if (snapshot_has_changed(old, ss)) {
198 198 free_snapshot(old);
199 199 old = NULL;
200 200 }
201 201
202 202 dovmstats(old, ss);
203 203 }
204 204
205 205 free_snapshot(old);
206 206 free_snapshot(ss);
207 207 free(df.if_names);
208 208 (void) kstat_close(kc);
209 209 return (0);
210 210 }
211 211
212 212 #define DELTA(v) (new->v - (old ? old->v : 0))
213 213 #define ADJ(n) ((adj <= 0) ? n : (adj >= n) ? 1 : n - adj)
214 214 #define adjprintf(fmt, n, val) adj -= (n + 1) - printf(fmt, ADJ(n), val)
215 215
216 216 static int adj; /* number of excess columns */
217 217
218 218 /*ARGSUSED*/
219 219 static void
220 220 show_disk(void *v1, void *v2, void *d)
221 221 {
222 222 struct iodev_snapshot *old = (struct iodev_snapshot *)v1;
223 223 struct iodev_snapshot *new = (struct iodev_snapshot *)v2;
224 224 hrtime_t oldtime = new->is_crtime;
225 225 double hr_etime;
226 226 double reads, writes;
227 227
228 228 if (new == NULL)
229 229 return;
230 230
231 231 if (old)
232 232 oldtime = old->is_stats.wlastupdate;
233 233 hr_etime = new->is_stats.wlastupdate - oldtime;
234 234 if (hr_etime == 0.0)
235 235 hr_etime = NANOSEC;
236 236 reads = new->is_stats.reads - (old ? old->is_stats.reads : 0);
237 237 writes = new->is_stats.writes - (old ? old->is_stats.writes : 0);
238 238 adjprintf(" %*.0f", 2, (reads + writes) / hr_etime * NANOSEC);
239 239 }
240 240
241 241 static void
242 242 dovmstats(struct snapshot *old, struct snapshot *new)
243 243 {
244 244 kstat_t *oldsys = NULL;
245 245 kstat_t *newsys = &new->s_sys.ss_agg_sys;
246 246 kstat_t *oldvm = NULL;
247 247 kstat_t *newvm = &new->s_sys.ss_agg_vm;
248 248 double percent_factor;
249 249 ulong_t sys_updates, vm_updates;
250 250 int count;
251 251
252 252 adj = 0;
253 253
254 254 if (old) {
255 255 oldsys = &old->s_sys.ss_agg_sys;
256 256 oldvm = &old->s_sys.ss_agg_vm;
257 257 }
258 258
259 259 etime = cpu_ticks_delta(oldsys, newsys);
260 260
261 261 percent_factor = 100.0 / denom(etime);
262 262 /*
263 263 * If any time has passed, convert etime to seconds per CPU
264 264 */
265 265 etime = etime >= 1.0 ? (etime / nr_active_cpus(new)) / hz : 1.0;
266 266 sys_updates = denom(DELTA(s_sys.ss_sysinfo.updates));
267 267 vm_updates = denom(DELTA(s_sys.ss_vminfo.updates));
268 268
269 269 if (timestamp_fmt != NODATE) {
270 270 print_timestamp(timestamp_fmt);
271 271 lines--;
272 272 }
273 273
274 274 if (--lines <= 0)
275 275 printhdr(0);
276 276
277 277 adj = 0;
278 278
279 279 if (pflag) {
280 280 adjprintf(" %*u", 6,
281 281 pgtok((int)(DELTA(s_sys.ss_vminfo.swap_avail)
282 282 / vm_updates)));
283 283 adjprintf(" %*u", 5,
284 284 pgtok((int)(DELTA(s_sys.ss_vminfo.freemem) / vm_updates)));
285 285 adjprintf(" %*.0f", 3, kstat_delta(oldvm, newvm, "pgrec")
286 286 / etime);
287 287 adjprintf(" %*.0f", 3, (kstat_delta(oldvm, newvm, "hat_fault") +
288 288 kstat_delta(oldvm, newvm, "as_fault")) / etime);
289 289 adjprintf(" %*.0f", 3, pgtok(kstat_delta(oldvm, newvm, "dfree"))
290 290 / etime);
291 291 adjprintf(" %*ld", 3, pgtok(new->s_sys.ss_deficit));
292 292 adjprintf(" %*.0f", 3, kstat_delta(oldvm, newvm, "scan")
293 293 / etime);
294 294 adjprintf(" %*.0f", 4,
295 295 pgtok(kstat_delta(oldvm, newvm, "execpgin")) / etime);
296 296 adjprintf(" %*.0f", 4,
297 297 pgtok(kstat_delta(oldvm, newvm, "execpgout")) / etime);
298 298 adjprintf(" %*.0f", 4,
299 299 pgtok(kstat_delta(oldvm, newvm, "execfree")) / etime);
300 300 adjprintf(" %*.0f", 4,
301 301 pgtok(kstat_delta(oldvm, newvm, "anonpgin")) / etime);
302 302 adjprintf(" %*.0f", 4,
303 303 pgtok(kstat_delta(oldvm, newvm, "anonpgout")) / etime);
304 304 adjprintf(" %*.0f", 4,
305 305 pgtok(kstat_delta(oldvm, newvm, "anonfree")) / etime);
306 306 adjprintf(" %*.0f", 4,
307 307 pgtok(kstat_delta(oldvm, newvm, "fspgin")) / etime);
308 308 adjprintf(" %*.0f", 4,
309 309 pgtok(kstat_delta(oldvm, newvm, "fspgout")) / etime);
310 310 adjprintf(" %*.0f\n", 4,
311 311 pgtok(kstat_delta(oldvm, newvm, "fsfree")) / etime);
312 312 (void) fflush(stdout);
↓ open down ↓ |
312 lines elided |
↑ open up ↑ |
313 313 return;
314 314 }
315 315
316 316 adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.runque) / sys_updates);
317 317 adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.waiting) / sys_updates);
318 318 adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.swpque) / sys_updates);
319 319 adjprintf(" %*u", 6, pgtok((int)(DELTA(s_sys.ss_vminfo.swap_avail)
320 320 / vm_updates)));
321 321 adjprintf(" %*u", 5, pgtok((int)(DELTA(s_sys.ss_vminfo.freemem)
322 322 / vm_updates)));
323 - adjprintf(" %*.0f", 3, swflag?
324 - kstat_delta(oldvm, newvm, "swapin") / etime :
323 + adjprintf(" %*.0f", 3, swflag? 0 :
325 324 kstat_delta(oldvm, newvm, "pgrec") / etime);
326 - adjprintf(" %*.0f", 3, swflag?
327 - kstat_delta(oldvm, newvm, "swapout") / etime :
325 + adjprintf(" %*.0f", 3, swflag? 0 :
328 326 (kstat_delta(oldvm, newvm, "hat_fault")
329 327 + kstat_delta(oldvm, newvm, "as_fault"))
330 328 / etime);
331 329 adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "pgpgin"))
332 330 / etime);
333 331 adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "pgpgout"))
334 332 / etime);
335 333 adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "dfree"))
336 334 / etime);
337 335 adjprintf(" %*ld", 2, pgtok(new->s_sys.ss_deficit));
338 336 adjprintf(" %*.0f", 2, kstat_delta(oldvm, newvm, "scan") / etime);
339 337
340 338 (void) snapshot_walk(SNAP_IODEVS, old, new, show_disk, NULL);
341 339
342 340 count = df.if_max_iodevs - new->s_nr_iodevs;
343 341 while (count-- > 0)
344 342 adjprintf(" %*d", 2, 0);
345 343
346 344 adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "intr") / etime);
347 345 adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "syscall") / etime);
348 346 adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "pswitch") / etime);
349 347 adjprintf(" %*.0f", 2,
350 348 kstat_delta(oldsys, newsys, "cpu_ticks_user") * percent_factor);
351 349 adjprintf(" %*.0f", 2, kstat_delta(oldsys, newsys, "cpu_ticks_kernel")
352 350 * percent_factor);
353 351 adjprintf(" %*.0f\n", 2, (kstat_delta(oldsys, newsys, "cpu_ticks_idle")
354 352 + kstat_delta(oldsys, newsys, "cpu_ticks_wait"))
355 353 * percent_factor);
356 354 (void) fflush(stdout);
357 355 }
358 356
359 357 /*ARGSUSED*/
360 358 static void
361 359 print_disk(void *v, void *v2, void *d)
362 360 {
363 361 struct iodev_snapshot *iodev = (struct iodev_snapshot *)v2;
364 362
365 363 if (iodev == NULL)
366 364 return;
367 365
368 366 (void) printf("%c%c ", iodev->is_name[0], iodev->is_name[2]);
369 367 }
370 368
371 369 /* ARGSUSED */
372 370 static void
373 371 printhdr(int sig)
374 372 {
375 373 int i = df.if_max_iodevs - ss->s_nr_iodevs;
376 374
377 375 if (sig == SIGCONT)
378 376 caught_cont = 1;
379 377
380 378 if (pflag) {
381 379 (void) printf(" memory page ");
382 380 (void) printf("executable anonymous filesystem \n");
383 381 (void) printf(" swap free re mf fr de sr ");
384 382 (void) printf("epi epo epf api apo apf fpi fpo fpf\n");
385 383 lines = REPRINT;
386 384 return;
387 385 }
388 386
389 387 (void) printf(" kthr memory page ");
390 388 (void) printf("disk faults cpu\n");
391 389
392 390 if (swflag)
393 391 (void) printf(" r b w swap free si so pi po fr de sr ");
394 392 else
395 393 (void) printf(" r b w swap free re mf pi po fr de sr ");
396 394
397 395 (void) snapshot_walk(SNAP_IODEVS, NULL, ss, print_disk, NULL);
398 396
399 397 while (i-- > 0)
400 398 (void) printf("-- ");
401 399
402 400 (void) printf(" in sy cs us sy id\n");
403 401 lines = REPRINT;
404 402 }
405 403
406 404 static void
407 405 sum_out(char const *pretty, kstat_t *ks, char *name)
408 406 {
↓ open down ↓ |
71 lines elided |
↑ open up ↑ |
409 407 kstat_named_t *ksn = kstat_data_lookup(ks, name);
410 408 if (ksn == NULL) {
411 409 fail(0, "kstat_data_lookup('%s', '%s') failed",
412 410 ks->ks_name, name);
413 411 }
414 412
415 413 (void) printf("%9llu %s\n", ksn->value.ui64, pretty);
416 414 }
417 415
418 416 static void
417 +zero_out(char const *pretty)
418 +{
419 + (void) printf("%9llu %s\n", 0, pretty);
420 +}
421 +
422 +static void
419 423 dosum(struct sys_snapshot *ss)
420 424 {
421 425 uint64_t total_faults;
422 426 kstat_named_t *ksn;
423 427 long double nchtotal;
424 428 uint64_t nchhits;
425 429
426 - sum_out("swap ins", &ss->ss_agg_vm, "swapin");
427 - sum_out("swap outs", &ss->ss_agg_vm, "swapout");
428 - sum_out("pages swapped in", &ss->ss_agg_vm, "pgswapin");
429 - sum_out("pages swapped out", &ss->ss_agg_vm, "pgswapout");
430 + zero_out("swap ins");
431 + zero_out("swap outs");
432 + zero_out("pages swapped in");
433 + zero_out("pages swapped out");
430 434
431 435 ksn = kstat_data_lookup(&ss->ss_agg_vm, "hat_fault");
432 436 if (ksn == NULL) {
433 437 fail(0, "kstat_data_lookup('%s', 'hat_fault') failed",
434 438 ss->ss_agg_vm.ks_name);
435 439 }
436 440 total_faults = ksn->value.ui64;
437 441 ksn = kstat_data_lookup(&ss->ss_agg_vm, "as_fault");
438 442 if (ksn == NULL) {
439 443 fail(0, "kstat_data_lookup('%s', 'as_fault') failed",
440 444 ss->ss_agg_vm.ks_name);
441 445 }
442 446 total_faults += ksn->value.ui64;
443 447
444 448 (void) printf("%9llu total address trans. faults taken\n",
445 449 total_faults);
446 450
447 451 sum_out("page ins", &ss->ss_agg_vm, "pgin");
448 452 sum_out("page outs", &ss->ss_agg_vm, "pgout");
449 453 sum_out("pages paged in", &ss->ss_agg_vm, "pgpgin");
450 454 sum_out("pages paged out", &ss->ss_agg_vm, "pgpgout");
451 455 sum_out("total reclaims", &ss->ss_agg_vm, "pgrec");
452 456 sum_out("reclaims from free list", &ss->ss_agg_vm, "pgfrec");
453 457 sum_out("micro (hat) faults", &ss->ss_agg_vm, "hat_fault");
454 458 sum_out("minor (as) faults", &ss->ss_agg_vm, "as_fault");
455 459 sum_out("major faults", &ss->ss_agg_vm, "maj_fault");
456 460 sum_out("copy-on-write faults", &ss->ss_agg_vm, "cow_fault");
457 461 sum_out("zero fill page faults", &ss->ss_agg_vm, "zfod");
458 462 sum_out("pages examined by the clock daemon", &ss->ss_agg_vm, "scan");
459 463 sum_out("revolutions of the clock hand", &ss->ss_agg_vm, "rev");
460 464 sum_out("pages freed by the clock daemon", &ss->ss_agg_vm, "dfree");
461 465 sum_out("forks", &ss->ss_agg_sys, "sysfork");
462 466 sum_out("vforks", &ss->ss_agg_sys, "sysvfork");
463 467 sum_out("execs", &ss->ss_agg_sys, "sysexec");
464 468 sum_out("cpu context switches", &ss->ss_agg_sys, "pswitch");
465 469 sum_out("device interrupts", &ss->ss_agg_sys, "intr");
466 470 sum_out("traps", &ss->ss_agg_sys, "trap");
467 471 sum_out("system calls", &ss->ss_agg_sys, "syscall");
468 472
469 473 nchtotal = (long double) ss->ss_nc.ncs_hits.value.ui64 +
470 474 (long double) ss->ss_nc.ncs_misses.value.ui64;
471 475 nchhits = ss->ss_nc.ncs_hits.value.ui64;
472 476 (void) printf("%9.0Lf total name lookups (cache hits %.0Lf%%)\n",
473 477 nchtotal, nchhits / denom(nchtotal) * 100);
474 478
475 479 sum_out("user cpu", &ss->ss_agg_sys, "cpu_ticks_user");
476 480 sum_out("system cpu", &ss->ss_agg_sys, "cpu_ticks_kernel");
477 481 sum_out("idle cpu", &ss->ss_agg_sys, "cpu_ticks_idle");
478 482 sum_out("wait cpu", &ss->ss_agg_sys, "cpu_ticks_wait");
479 483 }
480 484
481 485 static void
482 486 dointr(struct snapshot *ss)
483 487 {
484 488 size_t i;
485 489 ulong_t total = 0;
486 490
487 491 (void) printf("interrupt total rate\n");
488 492 (void) printf("--------------------------------\n");
489 493
490 494 for (i = 0; i < ss->s_nr_intrs; i++) {
491 495 (void) printf("%-12.8s %10lu %8.0f\n",
492 496 ss->s_intrs[i].is_name, ss->s_intrs[i].is_total,
493 497 ss->s_intrs[i].is_total / etime);
494 498 total += ss->s_intrs[i].is_total;
495 499 }
496 500
497 501 (void) printf("--------------------------------\n");
498 502 (void) printf("Total %10lu %8.0f\n", total, total / etime);
499 503 }
500 504
501 505 static void
502 506 usage(void)
503 507 {
504 508 (void) fprintf(stderr,
505 509 "Usage: vmstat [-ipqsS] [-T d|u] [disk ...] "
506 510 "[interval [count]]\n");
507 511 exit(1);
508 512 }
↓ open down ↓ |
69 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX