/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2009 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*
* 25-mar-99 A.Ramesh at Apple
* Ported to MacOS X
+ *
+ * 22-Jan-09 R.Branche at Apple
+ * Changed some fields to 64-bit to alleviate overflows
************************************************************************
*/
+#include <stddef.h>
+#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <mach/mach.h>
-vm_statistics_data_t vm_stat, last;
-int percent;
+vm_statistics64_data_t vm_stat, last;
+natural_t percent;
int delay;
char *pgmname;
mach_port_t myHost;
-int pageSize = 4096; /* set to 4k default */
+vm_size_t pageSize = 4096; /* set to 4k default */
-void usage();
-void banner();
-void snapshot();
-void pstat(char *str, int n);
-void print_stats();
-void get_stats(struct vm_statistics *stat);
+void usage(void);
+void snapshot(void);
+void sspstat(char *str, uint64_t n);
+void banner(void);
+void print_stats(void);
+void get_stats(vm_statistics64_t stat);
+
+void pstat(uint64_t n, int width);
int
-main(argc, argv)
- int argc;
- char *argv[];
+main(int argc, char *argv[])
{
pgmname = argv[0];
sleep(delay);
}
}
- exit(0);
+ exit(EXIT_SUCCESS);
}
void
-usage()
+usage(void)
{
fprintf(stderr, "usage: %s [ repeat-interval ]\n", pgmname);
- exit(1);
+ exit(EXIT_FAILURE);
}
void
-banner()
+snapshot(void)
+{
+
+ get_stats(&vm_stat);
+ printf("Mach Virtual Memory Statistics: (page size of %d bytes)\n",
+ (int) (pageSize));
+
+ sspstat("Pages free:", (uint64_t) (vm_stat.free_count - vm_stat.speculative_count));
+ sspstat("Pages active:", (uint64_t) (vm_stat.active_count));
+ sspstat("Pages inactive:", (uint64_t) (vm_stat.inactive_count));
+ sspstat("Pages speculative:", (uint64_t) (vm_stat.speculative_count));
+ sspstat("Pages wired down:", (uint64_t) (vm_stat.wire_count));
+ sspstat("\"Translation faults\":", (uint64_t) (vm_stat.faults));
+ sspstat("Pages copy-on-write:", (uint64_t) (vm_stat.cow_faults));
+ sspstat("Pages zero filled:", (uint64_t) (vm_stat.zero_fill_count));
+ sspstat("Pages reactivated:", (uint64_t) (vm_stat.reactivations));
+ sspstat("Pageins:", (uint64_t) (vm_stat.pageins));
+ sspstat("Pageouts:", (uint64_t) (vm_stat.pageouts));
+#if defined(__ppc__) /* vm_statistics are still 32-bit on ppc */
+ printf("Object cache: %u hits of %u lookups (%u%% hit rate)\n",
+#else
+ printf("Object cache: %llu hits of %llu lookups (%u%% hit rate)\n",
+#endif
+ vm_stat.hits, vm_stat.lookups, percent);
+
+}
+
+void
+sspstat(char *str, uint64_t n)
+{
+ printf("%-25s %16llu.\n", str, n);
+}
+
+void
+banner(void)
{
get_stats(&vm_stat);
printf("Mach Virtual Memory Statistics: ");
- printf("(page size of %d bytes, cache hits %d%%)\n",
- pageSize, percent);
- printf("%6s %6s %4s %4s %8s %8s %8s %8s %8s %8s\n",
+ printf("(page size of %d bytes, cache hits %u%%)\n",
+ (int) (pageSize), percent);
+ printf("%6s %6s %6s %8s %6s %8s %8s %8s %8s %8s %8s\n",
"free",
"active",
- "inac",
+ "spec",
+ "inactive",
"wire",
"faults",
"copy",
- "zerofill",
+ "0fill",
"reactive",
"pageins",
"pageout");
}
void
-snapshot()
-{
-
- get_stats(&vm_stat);
- printf("Mach Virtual Memory Statistics: (page size of %d bytes)\n",
- pageSize);
-
- pstat("Pages free:", vm_stat.free_count);
- pstat("Pages active:", vm_stat.active_count);
- pstat("Pages inactive:", vm_stat.inactive_count);
- pstat("Pages wired down:", vm_stat.wire_count);
- pstat("\"Translation faults\":", vm_stat.faults);
- pstat("Pages copy-on-write:", vm_stat.cow_faults);
- pstat("Pages zero filled:", vm_stat.zero_fill_count);
- pstat("Pages reactivated:", vm_stat.reactivations);
- pstat("Pageins:", vm_stat.pageins);
- pstat("Pageouts:", vm_stat.pageouts);
- printf("Object cache: %d hits of %d lookups (%d%% hit rate)\n",
- vm_stat.hits, vm_stat.lookups, percent);
-}
-
-void
-pstat(str, n)
- char *str;
- int n;
+print_stats(void)
{
- printf("%-25s %10d.\n", str, n);
-}
-
-void
-print_stats()
-{
- static count = 0;
+ static int count = 0;
if (count++ == 0)
banner();
count = 0;
get_stats(&vm_stat);
- printf("%6d %6d %4d %4d %8d %8d %8d %8d %8d %8d\n",
- vm_stat.free_count,
- vm_stat.active_count,
- vm_stat.inactive_count,
- vm_stat.wire_count,
- vm_stat.faults - last.faults,
- vm_stat.cow_faults - last.cow_faults,
- vm_stat.zero_fill_count - last.zero_fill_count,
- vm_stat.reactivations - last.reactivations,
- vm_stat.pageins - last.pageins,
- vm_stat.pageouts - last.pageouts);
+ pstat((uint64_t) (vm_stat.free_count - vm_stat.speculative_count), 6);
+ pstat((uint64_t) (vm_stat.active_count), 6);
+ pstat((uint64_t) (vm_stat.speculative_count), 6);
+ pstat((uint64_t) (vm_stat.inactive_count), 8);
+ pstat((uint64_t) (vm_stat.wire_count), 6);
+ pstat((uint64_t) (vm_stat.faults - last.faults), 8);
+ pstat((uint64_t) (vm_stat.cow_faults - last.cow_faults), 8);
+ pstat((uint64_t) (vm_stat.zero_fill_count - last.zero_fill_count), 8);
+ pstat((uint64_t) (vm_stat.reactivations - last.reactivations), 8);
+ pstat((uint64_t) (vm_stat.pageins - last.pageins), 8);
+ pstat((uint64_t) (vm_stat.pageouts - last.pageouts), 8);
+ putchar('\n');
last = vm_stat;
}
void
-get_stats(stat)
- struct vm_statistics *stat;
+pstat(uint64_t n, int width)
{
- int count = HOST_VM_INFO_COUNT;
- if (host_statistics(myHost, HOST_VM_INFO, stat,&count) != KERN_SUCCESS) {
- fprintf(stderr, "%s: failed to get statistics.\n", pgmname);
- exit(2);
+ char buf[80];
+ if (width >= sizeof(buf)) {
+ width = sizeof(buf) -1;
+ }
+
+ unsigned long long nb = n * (unsigned long long)pageSize;
+
+ /* Now that we have the speculative field, there is really not enough
+ space, but we were actually overflowing three or four fields before
+ anyway. So any field that overflows we drop some insignifigant
+ digets and slap on the appropriate suffix
+ */
+ int w = snprintf(buf, sizeof(buf), "%*llu", width, n);
+ if (w > width) {
+ w = snprintf(buf, sizeof(buf), "%*lluK", width -1, n / 1000);
+ if (w > width) {
+ w = snprintf(buf, sizeof(buf), "%*lluM", width -1, n / 1000000);
+ if (w > width) {
+ w = snprintf(buf, sizeof(buf), "%*lluG", width -1, n / 1000000000);
+ }
+ }
+ }
+ fputs(buf, stdout);
+ putchar(' ');
+}
+
+void
+get_stats(vm_statistics64_t stat)
+{
+ unsigned int count = HOST_VM_INFO64_COUNT;
+ kern_return_t ret;
+ if ((ret = host_statistics64(myHost, HOST_VM_INFO64, (host_info64_t)stat, &count) != KERN_SUCCESS)) {
+ fprintf(stderr, "%s: failed to get statistics. error %d\n", pgmname, ret);
+ exit(EXIT_FAILURE);
}
if (stat->lookups == 0)
percent = 0;
- else
- percent = (stat->hits*100)/stat->lookups;
+ else {
+ /*
+ * We have limited precision with the 32-bit natural_t fields
+ * in the vm_statistics structure. There's nothing we can do
+ * about counter overflows, but we can avoid percentage
+ * calculation overflows by doing the computation in floating
+ * point arithmetic ...
+ */
+ percent = (natural_t)(((double)stat->hits*100)/stat->lookups);
+ }
}