]> git.saurik.com Git - apple/system_cmds.git/blob - vm_stat.tproj/vm_stat.c
d7a45361bc1081a8cfbeb8b93be3bb2777cb2876
[apple/system_cmds.git] / vm_stat.tproj / vm_stat.c
1 /*
2 * Copyright (c) 1999-2009 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * File: vm_stat.c
26 * Author: Avadis Tevanian, Jr.
27 *
28 * Copyright (C) 1986, Avadis Tevanian, Jr.
29 *
30 *
31 * Display Mach VM statistics.
32 *
33 ************************************************************************
34 * HISTORY
35 * 6-Jun-86 Avadis Tevanian, Jr. (avie) at Carnegie-Mellon University
36 * Use official Mach interface.
37 *
38 * 25-mar-99 A.Ramesh at Apple
39 * Ported to MacOS X
40 *
41 * 22-Jan-09 R.Branche at Apple
42 * Changed some fields to 64-bit to alleviate overflows
43 ************************************************************************
44 */
45
46 #include <stddef.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <stdio.h>
50
51 #include <mach/mach.h>
52
53 vm_statistics64_data_t vm_stat, last;
54 natural_t percent;
55 int delay;
56 char *pgmname;
57 mach_port_t myHost;
58 vm_size_t pageSize = 4096; /* set to 4k default */
59
60 void usage(void);
61 void snapshot(void);
62 void sspstat(char *str, uint64_t n);
63 void banner(void);
64 void print_stats(void);
65 void get_stats(vm_statistics64_t stat);
66
67 void pstat(uint64_t n, int width);
68
69 int
70 main(int argc, char *argv[])
71 {
72
73 pgmname = argv[0];
74 delay = 0;
75
76
77 setlinebuf (stdout);
78
79 if (argc == 2) {
80 if (sscanf(argv[1], "%d", &delay) != 1)
81 usage();
82 if (delay < 0)
83 usage();
84 }
85
86 myHost = mach_host_self();
87
88 if(host_page_size(mach_host_self(), &pageSize) != KERN_SUCCESS) {
89 fprintf(stderr, "%s: failed to get pagesize; defaulting to 4K.\n", pgmname);
90 pageSize = 4096;
91 }
92
93 if (delay == 0) {
94 snapshot();
95 }
96 else {
97 while (1) {
98 print_stats();
99 sleep(delay);
100 }
101 }
102 exit(EXIT_SUCCESS);
103 }
104
105 void
106 usage(void)
107 {
108 fprintf(stderr, "usage: %s [ repeat-interval ]\n", pgmname);
109 exit(EXIT_FAILURE);
110 }
111
112 void
113 snapshot(void)
114 {
115
116 get_stats(&vm_stat);
117 printf("Mach Virtual Memory Statistics: (page size of %d bytes)\n",
118 (int) (pageSize));
119
120 sspstat("Pages free:", (uint64_t) (vm_stat.free_count - vm_stat.speculative_count));
121 sspstat("Pages active:", (uint64_t) (vm_stat.active_count));
122 sspstat("Pages inactive:", (uint64_t) (vm_stat.inactive_count));
123 sspstat("Pages speculative:", (uint64_t) (vm_stat.speculative_count));
124 sspstat("Pages wired down:", (uint64_t) (vm_stat.wire_count));
125 sspstat("\"Translation faults\":", (uint64_t) (vm_stat.faults));
126 sspstat("Pages copy-on-write:", (uint64_t) (vm_stat.cow_faults));
127 sspstat("Pages zero filled:", (uint64_t) (vm_stat.zero_fill_count));
128 sspstat("Pages reactivated:", (uint64_t) (vm_stat.reactivations));
129 sspstat("Pageins:", (uint64_t) (vm_stat.pageins));
130 sspstat("Pageouts:", (uint64_t) (vm_stat.pageouts));
131 #if defined(__ppc__) /* vm_statistics are still 32-bit on ppc */
132 printf("Object cache: %u hits of %u lookups (%u%% hit rate)\n",
133 #else
134 printf("Object cache: %llu hits of %llu lookups (%u%% hit rate)\n",
135 #endif
136 vm_stat.hits, vm_stat.lookups, percent);
137
138 }
139
140 void
141 sspstat(char *str, uint64_t n)
142 {
143 printf("%-25s %16llu.\n", str, n);
144 }
145
146 void
147 banner(void)
148 {
149 get_stats(&vm_stat);
150 printf("Mach Virtual Memory Statistics: ");
151 printf("(page size of %d bytes, cache hits %u%%)\n",
152 (int) (pageSize), percent);
153 printf("%6s %6s %6s %8s %6s %8s %8s %8s %8s %8s %8s\n",
154 "free",
155 "active",
156 "spec",
157 "inactive",
158 "wire",
159 "faults",
160 "copy",
161 "0fill",
162 "reactive",
163 "pageins",
164 "pageout");
165 bzero(&last, sizeof(last));
166 }
167
168 void
169 print_stats(void)
170 {
171 static int count = 0;
172
173 if (count++ == 0)
174 banner();
175
176 if (count > 20)
177 count = 0;
178
179 get_stats(&vm_stat);
180 pstat((uint64_t) (vm_stat.free_count - vm_stat.speculative_count), 6);
181 pstat((uint64_t) (vm_stat.active_count), 6);
182 pstat((uint64_t) (vm_stat.speculative_count), 6);
183 pstat((uint64_t) (vm_stat.inactive_count), 8);
184 pstat((uint64_t) (vm_stat.wire_count), 6);
185 pstat((uint64_t) (vm_stat.faults - last.faults), 8);
186 pstat((uint64_t) (vm_stat.cow_faults - last.cow_faults), 8);
187 pstat((uint64_t) (vm_stat.zero_fill_count - last.zero_fill_count), 8);
188 pstat((uint64_t) (vm_stat.reactivations - last.reactivations), 8);
189 pstat((uint64_t) (vm_stat.pageins - last.pageins), 8);
190 pstat((uint64_t) (vm_stat.pageouts - last.pageouts), 8);
191 putchar('\n');
192 last = vm_stat;
193 }
194
195 void
196 pstat(uint64_t n, int width)
197 {
198 char buf[80];
199 if (width >= sizeof(buf)) {
200 width = sizeof(buf) -1;
201 }
202
203 unsigned long long nb = n * (unsigned long long)pageSize;
204
205 /* Now that we have the speculative field, there is really not enough
206 space, but we were actually overflowing three or four fields before
207 anyway. So any field that overflows we drop some insignifigant
208 digets and slap on the appropriate suffix
209 */
210 int w = snprintf(buf, sizeof(buf), "%*llu", width, n);
211 if (w > width) {
212 w = snprintf(buf, sizeof(buf), "%*lluK", width -1, n / 1000);
213 if (w > width) {
214 w = snprintf(buf, sizeof(buf), "%*lluM", width -1, n / 1000000);
215 if (w > width) {
216 w = snprintf(buf, sizeof(buf), "%*lluG", width -1, n / 1000000000);
217 }
218 }
219 }
220 fputs(buf, stdout);
221 putchar(' ');
222 }
223
224 void
225 get_stats(vm_statistics64_t stat)
226 {
227 unsigned int count = HOST_VM_INFO64_COUNT;
228 if (host_statistics64(myHost, HOST_VM_INFO64, (host_info64_t)stat, &count) != KERN_SUCCESS) {
229 fprintf(stderr, "%s: failed to get statistics.\n", pgmname);
230 exit(EXIT_FAILURE);
231 }
232 if (stat->lookups == 0)
233 percent = 0;
234 else {
235 /*
236 * We have limited precision with the 32-bit natural_t fields
237 * in the vm_statistics structure. There's nothing we can do
238 * about counter overflows, but we can avoid percentage
239 * calculation overflows by doing the computation in floating
240 * point arithmetic ...
241 */
242 percent = (natural_t)(((double)stat->hits*100)/stat->lookups);
243 }
244 }