1#include <stdio.h> 2#include <stdlib.h> 3#include <signal.h> 4#include <setjmp.h> 5#include <mach/mach.h> 6#include <mach/mach_vm.h> 7#include <time.h> 8 9#define SUPERPAGE_SIZE (2*1024*1024) 10#define SUPERPAGE_MASK (-SUPERPAGE_SIZE) 11#define SUPERPAGE_ROUND_UP(a) ((a + SUPERPAGE_SIZE-1) & SUPERPAGE_MASK) 12 13#define RUNS0 100000 14#define STEP 4 /* KB */ 15#define START STEP 16#define MAX (1024*1024) /* KB */ 17 18#define RUNS1 RUNS0 19#define RUNS2 (RUNS0/20) 20 21clock_t 22testt(boolean_t superpages, int mode, int write, int kb) { 23 static int sum; 24 char *data; 25 unsigned int run, p, p2, i, res; 26 mach_vm_address_t addr = 0; 27 int pages = kb/4; 28 mach_vm_size_t size = SUPERPAGE_ROUND_UP(pages*PAGE_SIZE); /* allocate full superpages */ 29 int kr; 30 31 kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | (superpages? VM_FLAGS_SUPERPAGE_SIZE_2MB : VM_FLAGS_SUPERPAGE_NONE)); 32 33 if (!addr) 34 return 0; 35 36 data = (char*)(long)addr; 37 38 /* touch every base page to make sure everything is mapped and zero-filled */ 39 for (p = 0; p<pages; p++) { 40 sum += data[p*PAGE_SIZE]; 41 } 42 43 clock_t a = clock(); /* start timing */ 44 switch (mode) { 45 case 0: /* one byte every 4096 */ 46 if (write) { 47 for (run = 0; run < RUNS0; run++) { 48 for (p = 0; p<pages; p++) { 49 data[p*PAGE_SIZE] = run & 0xFF; 50 } 51 } 52 } else { 53 for (run = 0; run < RUNS0; run++) { 54 for (p = 0; p<pages; p++) { 55 sum += data[p*PAGE_SIZE]; 56 } 57 } 58 } 59 break; 60 case 1: /* every byte */ 61 if (write) { 62 for (run = 0; run < RUNS1/PAGE_SIZE; run++) { 63 for (i = 0; i<pages*PAGE_SIZE; i++) { 64 data[i] = run & 0xFF; 65 } 66 } 67 } else { 68 for (run = 0; run < RUNS1/PAGE_SIZE; run++) { 69 for (i = 0; i<pages*PAGE_SIZE; i++) { 70 sum += data[i]; 71 } 72 } 73 } 74 break; 75 case 2: /* random */ 76#define PRIME 15485863 77#define NODE_SIZE 128 /* bytes per node */ 78#define NODE_ACCESSES 16 /* accesses per node */ 79 p = 0; 80 if (write) { 81 for (run = 0; run < RUNS2*pages; run++) { 82 p += PRIME; 83 p2 = p % (pages*PAGE_SIZE/NODE_SIZE); 84//printf("p2 = %d\n", p2); 85 for (i = 0; i < NODE_ACCESSES; i++) { 86 data[p2*NODE_SIZE+i] = run & 0xFF; 87 } 88 } 89 } else { 90 for (run = 0; run < RUNS2*pages; run++) { 91 p += PRIME; 92 p2 = p % (pages*PAGE_SIZE/NODE_SIZE); 93 for (i = 0; i < NODE_ACCESSES; i++) { 94 sum += data[p2*NODE_SIZE+i]; 95 } 96 } 97 } 98 break; 99 } 100 clock_t b = clock(); /* stop timing */ 101 mach_vm_deallocate(mach_task_self(), addr, size); 102 res = b-a; 103 res /= pages; 104 return res; 105} 106 107int main(int argc, char **argv) { 108 int kb; 109 uint64_t time1, time2, time3, time4; 110 111 int mode; 112 113 printf("; m0 r s; m0 r b; m0 w s; m0 w b; m1 r s; m1 r b; m1 w s; m1 w b; m2 r s; m2 r b; m2 w s; m2 w b\n"); 114 for (kb=START; kb<MAX; kb+=STEP) { 115 printf("%d", kb); 116 for (mode=0; mode<=2; mode++) { 117 time1=time2=time3=time4=-1; 118 time1 = testt(TRUE, mode, 0, kb); // read super 119 time2 = testt(FALSE, mode, 0, kb); // read base 120 time3 = testt(TRUE, mode, 1, kb); // write super 121 time4 = testt(FALSE, mode, 1, kb); // write base 122 printf("; %lld; %lld; %lld; %lld", time1, time2, time3, time4); 123 fflush(stdout); 124 } 125 printf("\n"); 126 } 127 128 return 0; 129} 130