Home | History | Annotate | Download | only in pftest
      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