]> git.saurik.com Git - apple/xnu.git/blob - tools/tests/superpages/measure_tlbs.c
xnu-3248.60.10.tar.gz
[apple/xnu.git] / tools / tests / superpages / measure_tlbs.c
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
21 clock_t
22 testt(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
107 int 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 }