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