Print this page
4823 don't open-code NSEC2MSEC and MSEC2NSEC
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/rcap/rcapstat/rcapstat.c
+++ new/usr/src/cmd/rcap/rcapstat/rcapstat.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/stat.h>
28 28 #include <stdlib.h>
29 29 #include <fcntl.h>
30 30 #include <errno.h>
31 31 #include <stdio.h>
32 32 #include <unistd.h>
33 33 #include <string.h>
34 34 #include <strings.h>
35 35 #include <libintl.h>
36 36 #include <locale.h>
37 37
38 38 #include "rcapd.h"
39 39 #include "utils.h"
40 40 #include "rcapd_stat.h"
41 41 #include "statcommon.h"
42 42
43 43 static char mode[RC_MODE_LEN];
44 44 static rcapd_stat_hdr_t hdr;
45 45 static int global;
46 46 static int unformatted;
47 47 static time_t stat_mod = 0;
48 48
49 49 static uint_t timestamp_fmt = NODATE;
50 50
51 51 typedef struct col {
52 52 rcid_t col_id;
53 53 char col_name[LC_NAME_LEN];
54 54 uint64_t col_nproc;
55 55 uint64_t col_vmsize;
56 56 uint64_t col_rsssize;
57 57 uint64_t col_rsslimit;
58 58 uint64_t col_paged_eff;
59 59 uint64_t col_paged_eff_old;
60 60 uint64_t col_paged_eff_avg;
61 61 uint64_t col_paged_att;
62 62 uint64_t col_paged_att_old;
63 63 uint64_t col_paged_att_avg;
64 64 uint64_t col_count;
65 65 int col_fresh;
66 66 struct col *col_next;
67 67 struct col *col_prev;
68 68 lcollection_stat_t col_src_stat;
69 69 lcollection_stat_t col_old_stat;
70 70 } col_t;
71 71
72 72 static col_t *col_head;
73 73 static int ncol;
74 74
75 75 static col_t *
76 76 col_find(rcid_t id)
77 77 {
78 78 col_t *col;
79 79 for (col = col_head; col != NULL; col = col->col_next)
80 80 if (col->col_id.rcid_type == id.rcid_type &&
81 81 col->col_id.rcid_val == id.rcid_val)
82 82 return (col);
83 83 return (NULL);
84 84 }
85 85
86 86 static col_t *
87 87 col_insert(rcid_t id)
88 88 {
89 89 col_t *new_col;
90 90
91 91 new_col = malloc(sizeof (col_t));
92 92 if (new_col == NULL) {
93 93 (void) fprintf(stderr, gettext("rcapstat: malloc() failed\n"));
94 94 exit(E_ERROR);
95 95 }
96 96 (void) memset(new_col, 0, sizeof (col_t));
97 97 new_col->col_next = col_head;
98 98 new_col->col_id = id;
99 99 if (col_head != NULL)
100 100 col_head->col_prev = new_col;
101 101 col_head = new_col;
102 102 ncol++;
103 103 return (new_col);
104 104 }
105 105
106 106 static void
107 107 col_remove(col_t *col)
108 108 {
109 109 if (col->col_prev != NULL)
110 110 col->col_prev->col_next = col->col_next;
111 111 if (col->col_next != NULL)
112 112 col->col_next->col_prev = col->col_prev;
113 113 if (col_head == col)
114 114 col_head = col->col_next;
115 115 ncol--;
116 116 free(col);
117 117 }
118 118
119 119 static void
120 120 usage()
121 121 {
122 122 (void) fprintf(stderr,
123 123 gettext("usage: rcapstat [-g] [-p | -z] [-T d|u] "
124 124 "[interval [count]]\n"));
125 125 exit(E_USAGE);
126 126 }
127 127
128 128 static void
129 129 format_size(char *str, uint64_t size, int length)
130 130 {
131 131 char tag = 'K';
132 132 if (size >= 10000) {
133 133 size = (size + 512) / 1024;
134 134 tag = 'M';
135 135 if (size >= 10000) {
136 136 size = (size + 512) / 1024;
137 137 tag = 'G';
138 138 }
139 139 }
140 140 (void) snprintf(str, length, "%4lld%c", size, tag);
141 141 }
142 142
143 143 static int
144 144 read_stats(rcid_type_t stat_type)
145 145 {
146 146 int fd;
147 147 int proc_fd;
148 148 char procfile[20];
149 149 uint64_t pid;
150 150 col_t *col, *col_next;
151 151 lcollection_report_t report;
152 152 struct stat st;
153 153
154 154 if ((fd = open(STAT_FILE_DEFAULT, O_RDONLY)) < 0) {
155 155 warn(gettext("rcapd is not active\n"));
156 156 return (E_ERROR);
157 157 }
158 158
159 159 if (fstat(fd, &st) == 0)
160 160 stat_mod = st.st_mtime;
161 161
162 162 if (read(fd, &hdr, sizeof (hdr)) != sizeof (hdr)) {
163 163 (void) fprintf(stderr,
164 164 gettext("rcapstat: can't read stat file header: %s\n"),
165 165 strerror(errno));
166 166 (void) close(fd);
167 167 return (E_ERROR);
168 168 }
169 169
170 170 /*
171 171 * Check if rcapd is running
172 172 */
173 173 pid = hdr.rs_pid;
174 174 (void) snprintf(procfile, 20, "/proc/%lld/psinfo", pid);
175 175 if ((proc_fd = open(procfile, O_RDONLY)) < 0) {
176 176 warn(gettext("rcapd is not active\n"));
177 177 (void) close(fd);
178 178 return (E_ERROR);
179 179 }
180 180 (void) close(proc_fd);
181 181
182 182 (void) strncpy(mode, hdr.rs_mode, RC_MODE_LEN);
183 183 for (col = col_head; col != NULL; col = col->col_next) {
184 184 col->col_fresh = 0;
185 185 col->col_paged_eff = 0;
186 186 col->col_paged_att = 0;
187 187 }
188 188
189 189 while (read(fd, &report, sizeof (report)) == sizeof (report)) {
190 190 if (report.lcol_id.rcid_type != stat_type)
191 191 continue;
192 192
193 193 col = col_find(report.lcol_id);
194 194 if (col == NULL) {
195 195 col = col_insert(report.lcol_id);
196 196 col->col_paged_eff_old = col->col_paged_eff =
197 197 report.lcol_stat.lcols_pg_eff;
198 198 col->col_paged_att_old = col->col_paged_att =
199 199 report.lcol_stat.lcols_pg_att;
200 200 col->col_count = 0;
201 201 }
202 202 (void) strncpy(col->col_name, report.lcol_name, LC_NAME_LEN);
203 203 col->col_vmsize = report.lcol_image_size;
204 204 col->col_rsssize = report.lcol_rss;
205 205 col->col_rsslimit = report.lcol_rss_cap;
206 206 col->col_fresh = 1;
207 207 if (report.lcol_stat.lcols_pg_eff > col->col_paged_eff_old) {
208 208 col->col_paged_eff =
209 209 report.lcol_stat.lcols_pg_eff -
210 210 col->col_paged_eff_old;
211 211 if (report.lcol_stat.lcols_scan_count > col->col_count)
212 212 col->col_paged_eff_avg =
213 213 col->col_paged_eff /
214 214 (report.lcol_stat.lcols_scan_count -
215 215 col->col_count);
216 216 } else {
217 217 col->col_paged_eff_avg = 0;
218 218 }
219 219 if (report.lcol_stat.lcols_pg_att > col->col_paged_att_old) {
220 220 col->col_paged_att =
221 221 report.lcol_stat.lcols_pg_att -
222 222 col->col_paged_att_old;
223 223 if (report.lcol_stat.lcols_scan_count > col->col_count)
224 224 col->col_paged_att_avg =
225 225 col->col_paged_att /
226 226 (report.lcol_stat.lcols_scan_count -
227 227 col->col_count);
228 228 } else {
229 229 col->col_paged_att_avg = 0;
230 230 }
231 231 col->col_paged_eff_old = report.lcol_stat.lcols_pg_eff;
232 232 col->col_paged_att_old = report.lcol_stat.lcols_pg_att;
233 233 col->col_nproc =
234 234 report.lcol_stat.lcols_proc_in -
235 235 report.lcol_stat.lcols_proc_out;
236 236 col->col_count = report.lcol_stat.lcols_scan_count;
237 237 col->col_src_stat = report.lcol_stat;
238 238 }
239 239
240 240 /*
241 241 * Remove stale data
242 242 */
243 243 col = col_head;
244 244 while (col != NULL) {
245 245 col_next = col->col_next;
246 246 if (col->col_fresh == 0)
247 247 col_remove(col);
248 248 col = col_next;
249 249 }
250 250 (void) close(fd);
251 251 return (E_SUCCESS);
252 252 }
253 253
254 254 /*
255 255 * Print each collection's interval statistics.
256 256 */
257 257 /*ARGSUSED*/
258 258 static void
259 259 print_unformatted_stats(void)
260 260 {
261 261 col_t *col;
262 262
263 263 #define DELTA(field) \
264 264 (col->col_src_stat.field - col->col_old_stat.field)
265 265
266 266 col = col_head;
267 267 while (col != NULL) {
268 268 if (bcmp(&col->col_src_stat, &col->col_old_stat,
269 269 sizeof (col->col_src_stat)) == 0) {
270 270 col = col->col_next;
271 271 continue;
272 272 }
273 273 (void) printf("%s %s status: succeeded/attempted (k): "
↓ open down ↓ |
273 lines elided |
↑ open up ↑ |
274 274 "%llu/%llu, ineffective/scans/unenforced/samplings: "
275 275 "%llu/%llu/%llu/%llu, RSS min/max (k): %llu/%llu, cap %llu "
276 276 "kB, processes/thpt: %llu/%llu, %llu scans over %lld ms\n",
277 277 mode, col->col_name, DELTA(lcols_pg_eff),
278 278 DELTA(lcols_pg_att), DELTA(lcols_scan_ineffective),
279 279 DELTA(lcols_scan), DELTA(lcols_unenforced_cap),
280 280 DELTA(lcols_rss_sample), col->col_src_stat.lcols_min_rss,
281 281 col->col_src_stat.lcols_max_rss, col->col_rsslimit,
282 282 (col->col_src_stat.lcols_proc_in -
283 283 col->col_old_stat.lcols_proc_out), DELTA(lcols_proc_out),
284 - DELTA(lcols_scan_count), DELTA(lcols_scan_time_complete) /
285 - (NANOSEC / MILLISEC));
284 + DELTA(lcols_scan_count),
285 + NSEC2MSEC(DELTA(lcols_scan_time_complete)));
286 286 col->col_old_stat = col->col_src_stat;
287 287
288 288 col = col->col_next;
289 289 }
290 290
291 291 if (global)
292 292 (void) printf(gettext("physical memory utilization: %3u%% "
293 293 "cap enforcement threshold: %3u%%\n"), hdr.rs_pressure_cur,
294 294 hdr.rs_pressure_cap);
295 295 #undef DELTA
296 296 }
297 297
298 298 static void
299 299 print_stats(rcid_type_t stat_type)
300 300 {
301 301 col_t *col;
302 302 char size[6];
303 303 char limit[6];
304 304 char rss[6];
305 305 char nproc[6];
306 306 char paged_att[6];
307 307 char paged_eff[6];
308 308 char paged_att_avg[6];
309 309 char paged_eff_avg[6];
310 310 static int count = 0;
311 311
312 312 /*
313 313 * Print a header once every 20 times if we're only displaying reports
314 314 * for one collection (10 times if -g is used). Print a header every
315 315 * interval otherwise.
316 316 */
317 317 if (count == 0 || ncol != 1)
318 318 (void) printf("%6s %-15s %5s %5s %5s %5s %5s %5s %5s %5s\n",
319 319 "id", (stat_type == RCIDT_PROJECT ? "project" : "zone"),
320 320 "nproc", "vm", "rss", "cap",
321 321 "at", "avgat", "pg", "avgpg");
322 322 if (++count >= 20 || (count >= 10 && global != 0) || ncol != 1)
323 323 count = 0;
324 324
325 325 for (col = col_head; col != NULL; col = col->col_next) {
326 326 if (col->col_id.rcid_type != stat_type)
327 327 continue;
328 328
329 329 if (col->col_paged_att == 0)
330 330 (void) strlcpy(nproc, "-", sizeof (nproc));
331 331 else
332 332 (void) snprintf(nproc, sizeof (nproc), "%lld",
333 333 col->col_nproc);
334 334 format_size(size, col->col_vmsize, 6);
335 335 format_size(rss, col->col_rsssize, 6);
336 336 format_size(limit, col->col_rsslimit, 6);
337 337 format_size(paged_att, col->col_paged_att, 6);
338 338 format_size(paged_eff, col->col_paged_eff, 6);
339 339 format_size(paged_att_avg, col->col_paged_att_avg, 6);
340 340 format_size(paged_eff_avg, col->col_paged_eff_avg, 6);
341 341 (void) printf("%6lld %-15s %5s %5s %5s %5s %5s %5s %5s %5s\n",
342 342 col->col_id.rcid_val, col->col_name,
343 343 nproc,
344 344 size, rss, limit,
345 345 paged_att, paged_att_avg,
346 346 paged_eff, paged_eff_avg);
347 347 }
348 348 if (global)
349 349 (void) printf(gettext("physical memory utilization: %3u%% "
350 350 "cap enforcement threshold: %3u%%\n"), hdr.rs_pressure_cur,
351 351 hdr.rs_pressure_cap);
352 352 }
353 353
354 354 int
355 355 main(int argc, char *argv[])
356 356 {
357 357 int interval = 5;
358 358 int count;
359 359 int always = 1;
360 360 int opt;
361 361 int projects = 0;
362 362 int zones = 0;
363 363 /* project reporting is the default if no option is specified */
364 364 rcid_type_t stat_type = RCIDT_PROJECT;
365 365
366 366 (void) setlocale(LC_ALL, "");
367 367 (void) textdomain(TEXT_DOMAIN);
368 368 (void) setpname("rcapstat");
369 369
370 370 global = unformatted = 0;
371 371 while ((opt = getopt(argc, argv, "gpuzT:")) != (int)EOF) {
372 372 switch (opt) {
373 373 case 'g':
374 374 global = 1;
375 375 break;
376 376 case 'p':
377 377 projects = 1;
378 378 stat_type = RCIDT_PROJECT;
379 379 break;
380 380 case 'u':
381 381 unformatted = 1;
382 382 break;
383 383 case 'z':
384 384 stat_type = RCIDT_ZONE;
385 385 zones = 1;
386 386 break;
387 387 case 'T':
388 388 if (optarg) {
389 389 if (*optarg == 'u')
390 390 timestamp_fmt = UDATE;
391 391 else if (*optarg == 'd')
392 392 timestamp_fmt = DDATE;
393 393 else
394 394 usage();
395 395 } else {
396 396 usage();
397 397 }
398 398 break;
399 399 default:
400 400 usage();
401 401 }
402 402 }
403 403
404 404 if (argc > optind)
405 405 if ((interval = xatoi(argv[optind++])) <= 0)
406 406 die(gettext("invalid interval specified\n"));
407 407 if (argc > optind) {
408 408 if ((count = xatoi(argv[optind++])) <= 0)
409 409 die(gettext("invalid count specified\n"));
410 410 always = 0;
411 411 }
412 412 if (argc > optind || (projects > 0 && zones > 0))
413 413 usage();
414 414
415 415 while (always || count-- > 0) {
416 416 if (read_stats(stat_type) != E_SUCCESS)
417 417 return (E_ERROR);
418 418 if (timestamp_fmt != NODATE)
419 419 print_timestamp(timestamp_fmt);
420 420 if (!unformatted) {
421 421 print_stats(stat_type);
422 422 (void) fflush(stdout);
423 423 if (count || always)
424 424 (void) sleep(interval);
425 425 } else {
426 426 struct stat st;
427 427
428 428 print_unformatted_stats();
429 429 (void) fflush(stdout);
430 430 while (stat(STAT_FILE_DEFAULT, &st) == 0 &&
431 431 st.st_mtime == stat_mod)
432 432 (void) usleep((useconds_t)(0.2 * MICROSEC));
433 433 }
434 434 }
435 435
436 436 return (E_SUCCESS);
437 437 }
↓ open down ↓ |
142 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX