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 <err.h> 47#include <stddef.h> 48#include <stdlib.h> 49#include <unistd.h> 50#include <stdio.h> 51 52#include <mach/mach.h> 53 54vm_statistics64_data_t vm_stat, last; 55char *pgmname; 56mach_port_t myHost; 57vm_size_t pageSize = 4096; /* set to 4k default */ 58 59void usage(void); 60void snapshot(void); 61void sspstat(char *str, uint64_t n); 62void banner(void); 63void print_stats(void); 64void get_stats(vm_statistics64_t stat); 65 66void pstat(uint64_t n, int width); 67 68int 69main(int argc, char *argv[]) 70{ 71 72 double delay = 0.0; 73 int count = 0; 74 75 pgmname = argv[0]; 76 77 setlinebuf (stdout); 78 79 int c; 80 while ((c = getopt (argc, argv, "c:")) != -1) { 81 switch (c) { 82 case 'c': 83 count = (int)strtol(optarg, NULL, 10); 84 if (count < 1) { 85 warnx("count must be positive"); 86 usage(); 87 } 88 break; 89 default: 90 usage(); 91 break; 92 } 93 } 94 95 argc -= optind; argv += optind; 96 97 if (argc == 1) { 98 delay = strtod(argv[0], NULL); 99 if (delay < 0.0) 100 usage(); 101 } else if (argc > 1) { 102 usage(); 103 } 104 105 myHost = mach_host_self(); 106 107 if(host_page_size(mach_host_self(), &pageSize) != KERN_SUCCESS) { 108 fprintf(stderr, "%s: failed to get pagesize; defaulting to 4K.\n", pgmname); 109 pageSize = 4096; 110 } 111 112 if (delay == 0.0) { 113 snapshot(); 114 } else { 115 print_stats(); 116 for (int i = 1; i < count || count == 0; i++ ){ 117 usleep((int)(delay * USEC_PER_SEC)); 118 print_stats(); 119 } 120 } 121 exit(EXIT_SUCCESS); 122} 123 124void 125usage(void) 126{ 127 fprintf(stderr, "usage: %s [[-c count] interval]\n", pgmname); 128 exit(EXIT_FAILURE); 129} 130 131void 132snapshot(void) 133{ 134 135 get_stats(&vm_stat); 136 printf("Mach Virtual Memory Statistics: (page size of %d bytes)\n", 137 (int) (pageSize)); 138 139 sspstat("Pages free:", (uint64_t) (vm_stat.free_count - vm_stat.speculative_count)); 140 sspstat("Pages active:", (uint64_t) (vm_stat.active_count)); 141 sspstat("Pages inactive:", (uint64_t) (vm_stat.inactive_count)); 142 sspstat("Pages speculative:", (uint64_t) (vm_stat.speculative_count)); 143 sspstat("Pages throttled:", (uint64_t) (vm_stat.throttled_count)); 144 sspstat("Pages wired down:", (uint64_t) (vm_stat.wire_count)); 145 sspstat("Pages purgeable:", (uint64_t) (vm_stat.purgeable_count)); 146 sspstat("\"Translation faults\":", (uint64_t) (vm_stat.faults)); 147 sspstat("Pages copy-on-write:", (uint64_t) (vm_stat.cow_faults)); 148 sspstat("Pages zero filled:", (uint64_t) (vm_stat.zero_fill_count)); 149 sspstat("Pages reactivated:", (uint64_t) (vm_stat.reactivations)); 150 sspstat("Pages purged:", (uint64_t) (vm_stat.purges)); 151 sspstat("File-backed pages:", (uint64_t) (vm_stat.external_page_count)); 152 sspstat("Anonymous pages:", (uint64_t) (vm_stat.internal_page_count)); 153 sspstat("Pages stored in compressor:", (uint64_t) (vm_stat.total_uncompressed_pages_in_compressor)); 154 sspstat("Pages occupied by compressor:", (uint64_t) (vm_stat.compressor_page_count)); 155 sspstat("Decompressions:", (uint64_t) (vm_stat.decompressions)); 156 sspstat("Compressions:", (uint64_t) (vm_stat.compressions)); 157 sspstat("Pageins:", (uint64_t) (vm_stat.pageins)); 158 sspstat("Pageouts:", (uint64_t) (vm_stat.pageouts)); 159 sspstat("Swapins:", (uint64_t) (vm_stat.swapins)); 160 sspstat("Swapouts:", (uint64_t) (vm_stat.swapouts)); 161} 162 163void 164sspstat(char *str, uint64_t n) 165{ 166 printf("%-30s %16llu.\n", str, n); 167} 168 169void 170banner(void) 171{ 172 get_stats(&vm_stat); 173 printf("Mach Virtual Memory Statistics: "); 174 printf("(page size of %d bytes)\n", 175 (int) (pageSize)); 176 printf("%8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %11s %9s %8s %8s %8s %8s %8s %8s %8s %8s\n", 177 "free", 178 "active", 179 "specul", 180 "inactive", 181 "throttle", 182 "wired", 183 "prgable", 184 "faults", 185 "copy", 186 "0fill", 187 "reactive", 188 "purged", 189 "file-backed", 190 "anonymous", 191 "cmprssed", 192 "cmprssor", 193 "dcomprs", 194 "comprs", 195 "pageins", 196 "pageout", 197 "swapins", 198 "swapouts"); 199 bzero(&last, sizeof(last)); 200} 201 202void 203print_stats(void) 204{ 205 static int count = 0; 206 207 if (count++ == 0) 208 banner(); 209 210 if (count > 20) 211 count = 0; 212 213 get_stats(&vm_stat); 214 pstat((uint64_t) (vm_stat.free_count - vm_stat.speculative_count), 8); 215 pstat((uint64_t) (vm_stat.active_count), 8); 216 pstat((uint64_t) (vm_stat.speculative_count), 8); 217 pstat((uint64_t) (vm_stat.inactive_count), 8); 218 pstat((uint64_t) (vm_stat.throttled_count), 8); 219 pstat((uint64_t) (vm_stat.wire_count), 8); 220 pstat((uint64_t) (vm_stat.purgeable_count), 8); 221 pstat((uint64_t) (vm_stat.faults - last.faults), 8); 222 pstat((uint64_t) (vm_stat.cow_faults - last.cow_faults), 8); 223 pstat((uint64_t) (vm_stat.zero_fill_count - last.zero_fill_count), 8); 224 pstat((uint64_t) (vm_stat.reactivations - last.reactivations), 8); 225 pstat((uint64_t) (vm_stat.purges - last.purges), 8); 226 pstat((uint64_t) (vm_stat.external_page_count), 11); 227 pstat((uint64_t) (vm_stat.internal_page_count), 9); 228 pstat((uint64_t) (vm_stat.total_uncompressed_pages_in_compressor), 8); 229 pstat((uint64_t) (vm_stat.compressor_page_count), 8); 230 pstat((uint64_t) (vm_stat.decompressions - last.decompressions), 8); 231 pstat((uint64_t) (vm_stat.compressions - last.compressions), 8); 232 pstat((uint64_t) (vm_stat.pageins - last.pageins), 8); 233 pstat((uint64_t) (vm_stat.pageouts - last.pageouts), 8); 234 pstat((uint64_t) (vm_stat.swapins - last.swapins), 8); 235 pstat((uint64_t) (vm_stat.swapouts - last.swapouts), 8); 236 putchar('\n'); 237 last = vm_stat; 238} 239 240void 241pstat(uint64_t n, int width) 242{ 243 char buf[80]; 244 if (width >= sizeof(buf)) { 245 width = sizeof(buf) -1; 246 } 247 248 /* Now that we have the speculative field, there is really not enough 249 space, but we were actually overflowing three or four fields before 250 anyway. So any field that overflows we drop some insignifigant 251 digets and slap on the appropriate suffix 252 */ 253 int w = snprintf(buf, sizeof(buf), "%*llu", width, n); 254 if (w > width) { 255 w = snprintf(buf, sizeof(buf), "%*lluK", width -1, n / 1000); 256 if (w > width) { 257 w = snprintf(buf, sizeof(buf), "%*lluM", width -1, n / 1000000); 258 if (w > width) { 259 w = snprintf(buf, sizeof(buf), "%*lluG", width -1, n / 1000000000); 260 } 261 } 262 } 263 fputs(buf, stdout); 264 putchar(' '); 265} 266 267void 268get_stats(vm_statistics64_t stat) 269{ 270 unsigned int count = HOST_VM_INFO64_COUNT; 271 kern_return_t ret; 272 if ((ret = host_statistics64(myHost, HOST_VM_INFO64, (host_info64_t)stat, &count) != KERN_SUCCESS)) { 273 fprintf(stderr, "%s: failed to get statistics. error %d\n", pgmname, ret); 274 exit(EXIT_FAILURE); 275 } 276} 277