15 static const size_t pageSize = 4096;
20 int get() { return m_fd; }
21 void set(int fd) { m_fd = fd; }
23 Fd(int fd) : m_fd{fd} {}
32 void fillPageJunk(void *ptr)
34 uint64_t seed = (unsigned long long)rand() | ((unsigned long long)rand() << 32);
35 uint64_t *target = (uint64_t*)ptr;
36 for (int i = 0; i < pageSize / sizeof(uint64_t); i++) {
37 *target = seed ^ (uint64_t)(uintptr_t)target;
38 seed = (seed << 1) | ((seed >> 63) & 1);
46 void *m_ptr = nullptr;
54 FileMap(const string &name, size_t size, Hint hint = FILE_MAP_HINT_NONE) : m_name{name}, m_size{size} {
55 int fd = open(name.c_str(), O_CREAT | O_RDWR, S_IRWXU);
57 cout << "Error: open failed for " << name << ": " << strerror(errno) << endl;
61 fallocate(m_fileFd.get(), 0, 0, size);
63 m_ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fileFd.get(), 0);
64 if ((int)(uintptr_t)m_ptr == -1) {
65 cout << "Error: mmap failed: " << (int)(uintptr_t)m_ptr << ": " << strerror(errno) << endl;
69 case FILE_MAP_HINT_NONE: break;
70 case FILE_MAP_HINT_RAND:
71 madvise(m_ptr, m_size, MADV_RANDOM);
73 case FILE_MAP_HINT_LINEAR:
74 madvise(m_ptr, m_size, MADV_SEQUENTIAL);
77 for (int i = 0; i < m_size / pageSize; i++) {
78 uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * i;
79 fillPageJunk(targetPtr);
82 double benchRandom(bool write) {
83 size_t pagesTotal = m_size / pageSize;
84 size_t pagesToHit = pagesTotal / 128;
87 chrono::time_point<chrono::high_resolution_clock> start, end;
88 start = chrono::high_resolution_clock::now();
89 for (int j = 0; j < pagesToHit; j++) {
90 int targetPage = rand() % pagesTotal;
91 uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * targetPage;
99 end = chrono::high_resolution_clock::now();
100 nsTotal += chrono::duration_cast<chrono::nanoseconds>(end - start).count();
101 return ((4096.0 * pagesToHit) / (1 << 20)) / (nsTotal / 1.0E9);
103 double benchLinear(bool write) {
104 int pagesTotal = m_size / pageSize;
106 uint64_t nsTotal = 0;
108 chrono::time_point<chrono::high_resolution_clock> start, end;
109 start = chrono::high_resolution_clock::now();
110 for (int i = 0; i < iterations; i++) {
111 for (int j = 0; j < pagesTotal; j++) {
112 uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * j;
121 end = chrono::high_resolution_clock::now();
122 nsTotal += chrono::duration_cast<chrono::nanoseconds>(end - start).count();
123 return ((4096.0 * pagesTotal * iterations) / (1 << 20)) / (nsTotal / 1.0E9 );
126 int ret1 = msync(m_ptr, m_size, MS_SYNC | MS_INVALIDATE);
127 madvise(m_ptr, m_size, MADV_DONTNEED);
132 munmap(m_ptr, m_size);
137 int main(int argc, char *argv[])
139 double randomRead, randomWrite, linearRead, linearWrite;
144 fsize = 1024 * (1ull << 20);
145 else if (argc == 2) {
146 long long sz = atoll(argv[1]);
147 if (sz > 0 && (sz << 20) < SIZE_MAX)
148 fsize = atoll(argv[1]) * (1ull << 20);
152 cout << "Error: invalid argument" << endl;
153 cerr << "Usage: " << argv[0] << " [fsize_in_MB]" << endl;
156 cerr << "Using filesize=" << fsize << endl;
159 cerr << "Running random_read..." << endl;
160 FileMap file{"/data/local/tmp/mmap_test", fsize};
161 randomRead = file.benchRandom(false);
164 cerr << "Running linear_read..." << endl;
165 FileMap file{"/data/local/tmp/mmap_test", fsize};
166 linearRead = file.benchLinear(false);
169 cerr << "Running random_write..." << endl;
170 FileMap file{"/data/local/tmp/mmap_test", fsize};
171 randomWrite = file.benchRandom(true);
174 cerr << "Running linear_write..." << endl;
175 FileMap file{"/data/local/tmp/mmap_test", fsize};
176 linearWrite = file.benchLinear(true);
178 cout << "Success" << endl;
179 cout << "random_read : " << randomRead << " : MB/s" << endl;
180 cout << "linear_read : " << linearRead << " : MB/s" << endl;
181 cout << "random_write : " << randomWrite << " : MB/s" << endl;
182 cout << "linear_write : " << linearWrite << " : MB/s" << endl;