1*288bf522SAndroid Build Coastguard Worker #include <benchmark/benchmark.h>
2*288bf522SAndroid Build Coastguard Worker
3*288bf522SAndroid Build Coastguard Worker #include <string>
4*288bf522SAndroid Build Coastguard Worker #include <cstring>
5*288bf522SAndroid Build Coastguard Worker #include <cstdlib>
6*288bf522SAndroid Build Coastguard Worker #include <cstdio>
7*288bf522SAndroid Build Coastguard Worker #include <iostream>
8*288bf522SAndroid Build Coastguard Worker #include <vector>
9*288bf522SAndroid Build Coastguard Worker #include <tuple>
10*288bf522SAndroid Build Coastguard Worker
11*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
12*288bf522SAndroid Build Coastguard Worker #include <sys/stat.h>
13*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
14*288bf522SAndroid Build Coastguard Worker #include <sys/mman.h>
15*288bf522SAndroid Build Coastguard Worker
16*288bf522SAndroid Build Coastguard Worker using namespace std;
17*288bf522SAndroid Build Coastguard Worker static const size_t pageSize = getpagesize();
18*288bf522SAndroid Build Coastguard Worker static size_t fsize = 1024 * (1ull << 20);
19*288bf522SAndroid Build Coastguard Worker static size_t pagesTotal = fsize / pageSize;
20*288bf522SAndroid Build Coastguard Worker
21*288bf522SAndroid Build Coastguard Worker class Fd {
22*288bf522SAndroid Build Coastguard Worker int m_fd = -1;
23*288bf522SAndroid Build Coastguard Worker public:
get()24*288bf522SAndroid Build Coastguard Worker int get() { return m_fd; }
set(int fd)25*288bf522SAndroid Build Coastguard Worker void set(int fd) { m_fd = fd; }
Fd()26*288bf522SAndroid Build Coastguard Worker Fd() {}
Fd(int fd)27*288bf522SAndroid Build Coastguard Worker explicit Fd(int fd) : m_fd{fd} {}
~Fd()28*288bf522SAndroid Build Coastguard Worker ~Fd() {
29*288bf522SAndroid Build Coastguard Worker if (m_fd >= 0)
30*288bf522SAndroid Build Coastguard Worker close(m_fd);
31*288bf522SAndroid Build Coastguard Worker }
32*288bf522SAndroid Build Coastguard Worker };
33*288bf522SAndroid Build Coastguard Worker
34*288bf522SAndroid Build Coastguard Worker int dummy = 0;
35*288bf522SAndroid Build Coastguard Worker
fillPageJunk(void * ptr)36*288bf522SAndroid Build Coastguard Worker void fillPageJunk(void *ptr)
37*288bf522SAndroid Build Coastguard Worker {
38*288bf522SAndroid Build Coastguard Worker uint64_t seed = (unsigned long long)rand() | ((unsigned long long)rand() << 32);
39*288bf522SAndroid Build Coastguard Worker uint64_t *target = (uint64_t*)ptr;
40*288bf522SAndroid Build Coastguard Worker for (int i = 0; i < pageSize / sizeof(uint64_t); i++) {
41*288bf522SAndroid Build Coastguard Worker *target = seed ^ (uint64_t)(uintptr_t)target;
42*288bf522SAndroid Build Coastguard Worker seed = (seed << 1) | ((seed >> 63) & 1);
43*288bf522SAndroid Build Coastguard Worker target++;
44*288bf522SAndroid Build Coastguard Worker }
45*288bf522SAndroid Build Coastguard Worker }
46*288bf522SAndroid Build Coastguard Worker
47*288bf522SAndroid Build Coastguard Worker class FileMap {
48*288bf522SAndroid Build Coastguard Worker string m_name;
49*288bf522SAndroid Build Coastguard Worker size_t m_size;
50*288bf522SAndroid Build Coastguard Worker void *m_ptr = nullptr;
51*288bf522SAndroid Build Coastguard Worker Fd m_fileFd;
52*288bf522SAndroid Build Coastguard Worker public:
53*288bf522SAndroid Build Coastguard Worker enum Hint {
54*288bf522SAndroid Build Coastguard Worker FILE_MAP_HINT_NONE,
55*288bf522SAndroid Build Coastguard Worker FILE_MAP_HINT_RAND,
56*288bf522SAndroid Build Coastguard Worker FILE_MAP_HINT_LINEAR,
57*288bf522SAndroid Build Coastguard Worker };
FileMap(const string & name,size_t size,Hint hint=FILE_MAP_HINT_NONE)58*288bf522SAndroid Build Coastguard Worker FileMap(const string &name, size_t size, Hint hint = FILE_MAP_HINT_NONE) : m_name{name}, m_size{size} {
59*288bf522SAndroid Build Coastguard Worker int fd = open(name.c_str(), O_CREAT | O_RDWR, S_IRWXU);
60*288bf522SAndroid Build Coastguard Worker if (fd < 0) {
61*288bf522SAndroid Build Coastguard Worker cout << "Error: open failed for " << name << ": " << strerror(errno) << endl;
62*288bf522SAndroid Build Coastguard Worker exit(1);
63*288bf522SAndroid Build Coastguard Worker }
64*288bf522SAndroid Build Coastguard Worker m_fileFd.set(fd);
65*288bf522SAndroid Build Coastguard Worker fallocate(m_fileFd.get(), 0, 0, size);
66*288bf522SAndroid Build Coastguard Worker unlink(name.c_str());
67*288bf522SAndroid Build Coastguard Worker m_ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fileFd.get(), 0);
68*288bf522SAndroid Build Coastguard Worker if ((int)(uintptr_t)m_ptr == -1) {
69*288bf522SAndroid Build Coastguard Worker cout << "Error: mmap failed: " << (int)(uintptr_t)m_ptr << ": " << strerror(errno) << endl;
70*288bf522SAndroid Build Coastguard Worker exit(1);
71*288bf522SAndroid Build Coastguard Worker }
72*288bf522SAndroid Build Coastguard Worker switch (hint) {
73*288bf522SAndroid Build Coastguard Worker case FILE_MAP_HINT_NONE: break;
74*288bf522SAndroid Build Coastguard Worker case FILE_MAP_HINT_RAND:
75*288bf522SAndroid Build Coastguard Worker madvise(m_ptr, m_size, MADV_RANDOM);
76*288bf522SAndroid Build Coastguard Worker break;
77*288bf522SAndroid Build Coastguard Worker case FILE_MAP_HINT_LINEAR:
78*288bf522SAndroid Build Coastguard Worker madvise(m_ptr, m_size, MADV_SEQUENTIAL);
79*288bf522SAndroid Build Coastguard Worker break;
80*288bf522SAndroid Build Coastguard Worker }
81*288bf522SAndroid Build Coastguard Worker for (int i = 0; i < m_size / pageSize; i++) {
82*288bf522SAndroid Build Coastguard Worker uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * i;
83*288bf522SAndroid Build Coastguard Worker fillPageJunk(targetPtr);
84*288bf522SAndroid Build Coastguard Worker }
85*288bf522SAndroid Build Coastguard Worker }
benchRandomRead(unsigned int targetPage)86*288bf522SAndroid Build Coastguard Worker void benchRandomRead(unsigned int targetPage) {
87*288bf522SAndroid Build Coastguard Worker uint8_t *targetPtr = (uint8_t*)m_ptr + pageSize * targetPage;
88*288bf522SAndroid Build Coastguard Worker dummy += *targetPtr;
89*288bf522SAndroid Build Coastguard Worker }
benchRandomWrite(unsigned int targetPage)90*288bf522SAndroid Build Coastguard Worker void benchRandomWrite(unsigned int targetPage) {
91*288bf522SAndroid Build Coastguard Worker uint8_t *targetPtr = (uint8_t*)m_ptr + pageSize * targetPage;
92*288bf522SAndroid Build Coastguard Worker *targetPtr = dummy;
93*288bf522SAndroid Build Coastguard Worker }
benchLinearRead(unsigned int j)94*288bf522SAndroid Build Coastguard Worker void benchLinearRead(unsigned int j) {
95*288bf522SAndroid Build Coastguard Worker uint8_t *targetPtr = (uint8_t*)m_ptr + pageSize * j;
96*288bf522SAndroid Build Coastguard Worker dummy += *targetPtr;
97*288bf522SAndroid Build Coastguard Worker }
benchLinearWrite(unsigned int j)98*288bf522SAndroid Build Coastguard Worker void benchLinearWrite(unsigned int j) {
99*288bf522SAndroid Build Coastguard Worker uint8_t *targetPtr = (uint8_t*)m_ptr + pageSize * j;
100*288bf522SAndroid Build Coastguard Worker *targetPtr = dummy;
101*288bf522SAndroid Build Coastguard Worker }
dropCache()102*288bf522SAndroid Build Coastguard Worker void dropCache() {
103*288bf522SAndroid Build Coastguard Worker int ret1 = msync(m_ptr, m_size, MS_SYNC | MS_INVALIDATE);
104*288bf522SAndroid Build Coastguard Worker madvise(m_ptr, m_size, MADV_DONTNEED);
105*288bf522SAndroid Build Coastguard Worker (void)ret1;
106*288bf522SAndroid Build Coastguard Worker }
~FileMap()107*288bf522SAndroid Build Coastguard Worker ~FileMap() {
108*288bf522SAndroid Build Coastguard Worker if (m_ptr)
109*288bf522SAndroid Build Coastguard Worker munmap(m_ptr, m_size);
110*288bf522SAndroid Build Coastguard Worker }
111*288bf522SAndroid Build Coastguard Worker
112*288bf522SAndroid Build Coastguard Worker };
113*288bf522SAndroid Build Coastguard Worker
benchRandomRead(benchmark::State & state)114*288bf522SAndroid Build Coastguard Worker static void benchRandomRead(benchmark::State& state) {
115*288bf522SAndroid Build Coastguard Worker FileMap file{"/data/local/tmp/mmap_test", fsize};
116*288bf522SAndroid Build Coastguard Worker while (state.KeepRunning()) {
117*288bf522SAndroid Build Coastguard Worker unsigned int targetPage = rand() % pagesTotal;
118*288bf522SAndroid Build Coastguard Worker file.benchRandomRead(targetPage);
119*288bf522SAndroid Build Coastguard Worker }
120*288bf522SAndroid Build Coastguard Worker state.SetBytesProcessed(state.iterations() * pageSize);
121*288bf522SAndroid Build Coastguard Worker }
122*288bf522SAndroid Build Coastguard Worker BENCHMARK(benchRandomRead);
123*288bf522SAndroid Build Coastguard Worker
benchRandomWrite(benchmark::State & state)124*288bf522SAndroid Build Coastguard Worker static void benchRandomWrite(benchmark::State& state) {
125*288bf522SAndroid Build Coastguard Worker FileMap file{"/data/local/tmp/mmap_test", fsize};
126*288bf522SAndroid Build Coastguard Worker while (state.KeepRunning()) {
127*288bf522SAndroid Build Coastguard Worker unsigned int targetPage = rand() % pagesTotal;
128*288bf522SAndroid Build Coastguard Worker file.benchRandomWrite(targetPage);
129*288bf522SAndroid Build Coastguard Worker }
130*288bf522SAndroid Build Coastguard Worker state.SetBytesProcessed(state.iterations() * pageSize);
131*288bf522SAndroid Build Coastguard Worker }
132*288bf522SAndroid Build Coastguard Worker BENCHMARK(benchRandomWrite);
133*288bf522SAndroid Build Coastguard Worker
benchLinearRead(benchmark::State & state)134*288bf522SAndroid Build Coastguard Worker static void benchLinearRead(benchmark::State& state) {
135*288bf522SAndroid Build Coastguard Worker FileMap file{"/data/local/tmp/mmap_test", fsize};
136*288bf522SAndroid Build Coastguard Worker unsigned int j = 0;
137*288bf522SAndroid Build Coastguard Worker while (state.KeepRunning()) {
138*288bf522SAndroid Build Coastguard Worker file.benchLinearRead(j);
139*288bf522SAndroid Build Coastguard Worker j = (j + 1) % pagesTotal;
140*288bf522SAndroid Build Coastguard Worker }
141*288bf522SAndroid Build Coastguard Worker state.SetBytesProcessed(state.iterations() * pageSize);
142*288bf522SAndroid Build Coastguard Worker }
143*288bf522SAndroid Build Coastguard Worker BENCHMARK(benchLinearRead);
144*288bf522SAndroid Build Coastguard Worker
benchLinearWrite(benchmark::State & state)145*288bf522SAndroid Build Coastguard Worker static void benchLinearWrite(benchmark::State& state) {
146*288bf522SAndroid Build Coastguard Worker FileMap file{"/data/local/tmp/mmap_test", fsize};
147*288bf522SAndroid Build Coastguard Worker unsigned int j = 0;
148*288bf522SAndroid Build Coastguard Worker while (state.KeepRunning()) {
149*288bf522SAndroid Build Coastguard Worker file.benchLinearWrite(j);
150*288bf522SAndroid Build Coastguard Worker j = (j + 1) % pagesTotal;
151*288bf522SAndroid Build Coastguard Worker }
152*288bf522SAndroid Build Coastguard Worker state.SetBytesProcessed(state.iterations() * pageSize);
153*288bf522SAndroid Build Coastguard Worker }
154*288bf522SAndroid Build Coastguard Worker BENCHMARK(benchLinearWrite);
155*288bf522SAndroid Build Coastguard Worker
156*288bf522SAndroid Build Coastguard Worker BENCHMARK_MAIN();
157