1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <stdint.h> 20 #include <unistd.h> 21 #include <sys/time.h> 22 #include <time.h> 23 24 #define N_PAGES (4096) 25 26 #define WARMUP (1<<10) 27 28 #define WORKLOAD (1<<24) 29 30 int numPagesList[] = { 31 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 32 12, 14, 16, 18, 20, 24, 28, 30, 32, 34, 48, 62, 64, 66, 80, 33 96, 112, 128, 144, 160, 320, 480, 496, 512, 528, 544, 576, 640, 960, 34 1024, 2048, 3072, 4000, 35 }; 36 37 static unsigned long long stop_watch() 38 { 39 struct timespec t; 40 t.tv_sec = t.tv_nsec = 0; 41 clock_gettime(CLOCK_MONOTONIC, &t); 42 return t.tv_sec*1000000000ULL + t.tv_nsec; 43 } 44 45 int main() 46 { 47 char *mem = malloc((N_PAGES+1) * 4096); 48 intptr_t *p; 49 int i; 50 unsigned int j; 51 52 /* Align to page start */ 53 mem = (char *) ((intptr_t) (mem + 4096) & ~0xfff); 54 55 for (j = 0; j < sizeof(numPagesList)/sizeof(int); j++) { 56 int numPages = numPagesList[j]; 57 int pageIdx = 0; 58 int entryOffset = 0; 59 60 /* 61 * page 0 page 1 page 2 .... page N 62 * ------ ------ ------ ------ 63 * word 0 -> word 0 -> word 0 -> .... -> word 0 -> (page 0/word 0) 64 * : : : : : 65 * word 1023 word 1023 word 1023 : word 1023 66 */ 67 for (i = 0; i < numPages; i++) { 68 int nextPageIdx = (pageIdx + 1) % numPages; 69 /* Looks like spread the pointer across cache lines introduce noise 70 * to get to the asymptote 71 * int nextEntryOffset = (entryOffset + 32) % 1024; 72 */ 73 int nextEntryOffset = entryOffset; 74 75 if (i != numPages -1) { 76 *(intptr_t *) (mem + 4096 * pageIdx + entryOffset) = 77 (intptr_t) (mem + 4096 * nextPageIdx + nextEntryOffset); 78 } else { 79 /* Last page - form the cycle */ 80 *(intptr_t *) (mem + 4096 * pageIdx + entryOffset) = 81 (intptr_t) &mem[0]; 82 } 83 84 pageIdx = nextPageIdx; 85 entryOffset = nextEntryOffset; 86 } 87 88 /* Starting point of the pointer chase */ 89 p = (intptr_t *) &mem[0]; 90 91 /* Warmup (ie pre-thrash the memory system */ 92 for (i = 0; i < WARMUP; i++) { 93 p = (intptr_t *) *p; 94 } 95 96 /* Real work */ 97 unsigned long long t0 = stop_watch(); 98 for (i = 0; i < WORKLOAD; i++) { 99 p = (intptr_t *) *p; 100 } 101 unsigned long long t1 = stop_watch(); 102 103 /* To keep p from being optimized by gcc */ 104 if (p) 105 printf("%d, %f\n", numPages, (float) (t1 - t0) / WORKLOAD); 106 } 107 return 0; 108 } 109