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