1df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez#include "benchmark/benchmark_api.h" 26e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <string> 36e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <cstring> 46e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <cstdlib> 56e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <cstdio> 66e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <iostream> 76e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <vector> 86e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <tuple> 96e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews 106e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <unistd.h> 116e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <sys/stat.h> 126e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <fcntl.h> 136e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews#include <sys/mman.h> 146e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews 156e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrewsusing namespace std; 16df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprezstatic const size_t pageSize = PAGE_SIZE; 17df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprezstatic size_t fsize = 1024 * (1ull << 20); 18df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprezstatic size_t pagesTotal = fsize / pageSize; 196e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews 206e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrewsclass Fd { 216e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews int m_fd = -1; 226e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrewspublic: 236e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews int get() { return m_fd; } 246e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews void set(int fd) { m_fd = fd; } 256e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews Fd() {} 266fbd1a930a0f53bd392259ad12dd94c45305d2c8Chih-Hung Hsieh explicit Fd(int fd) : m_fd{fd} {} 276e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews ~Fd() { 286e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews if (m_fd >= 0) 296e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews close(m_fd); 306e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 316e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews}; 326e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews 336e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrewsint dummy = 0; 346e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews 356e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrewsvoid fillPageJunk(void *ptr) 366e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews{ 376e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews uint64_t seed = (unsigned long long)rand() | ((unsigned long long)rand() << 32); 386e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews uint64_t *target = (uint64_t*)ptr; 396e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews for (int i = 0; i < pageSize / sizeof(uint64_t); i++) { 406e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews *target = seed ^ (uint64_t)(uintptr_t)target; 416e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews seed = (seed << 1) | ((seed >> 63) & 1); 426e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews target++; 436e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 446e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews} 456e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews 466e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrewsclass FileMap { 476e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews string m_name; 486e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews size_t m_size; 496e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews void *m_ptr = nullptr; 506e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews Fd m_fileFd; 516e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrewspublic: 526e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews enum Hint { 536e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews FILE_MAP_HINT_NONE, 546e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews FILE_MAP_HINT_RAND, 556e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews FILE_MAP_HINT_LINEAR, 566e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews }; 576e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews FileMap(const string &name, size_t size, Hint hint = FILE_MAP_HINT_NONE) : m_name{name}, m_size{size} { 586e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews int fd = open(name.c_str(), O_CREAT | O_RDWR, S_IRWXU); 596e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews if (fd < 0) { 607d20a66002e9a42face7a331d8a72facaddab0faTodd Kjos cout << "Error: open failed for " << name << ": " << strerror(errno) << endl; 617d20a66002e9a42face7a331d8a72facaddab0faTodd Kjos exit(1); 626e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 636e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews m_fileFd.set(fd); 646e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews fallocate(m_fileFd.get(), 0, 0, size); 656e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews unlink(name.c_str()); 666e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews m_ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fileFd.get(), 0); 676e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews if ((int)(uintptr_t)m_ptr == -1) { 687d20a66002e9a42face7a331d8a72facaddab0faTodd Kjos cout << "Error: mmap failed: " << (int)(uintptr_t)m_ptr << ": " << strerror(errno) << endl; 697d20a66002e9a42face7a331d8a72facaddab0faTodd Kjos exit(1); 706e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 716e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews switch (hint) { 726e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews case FILE_MAP_HINT_NONE: break; 736e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews case FILE_MAP_HINT_RAND: 746e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews madvise(m_ptr, m_size, MADV_RANDOM); 756e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews break; 766e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews case FILE_MAP_HINT_LINEAR: 776e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews madvise(m_ptr, m_size, MADV_SEQUENTIAL); 786e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews break; 796e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 806e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews for (int i = 0; i < m_size / pageSize; i++) { 816e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * i; 826e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews fillPageJunk(targetPtr); 836e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 846e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 85df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez void benchRandomRead(unsigned int targetPage) { 86df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez uint8_t *targetPtr = (uint8_t*)m_ptr + pageSize * targetPage; 87df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez dummy += *targetPtr; 886e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 89df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez void benchRandomWrite(unsigned int targetPage) { 90df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez uint8_t *targetPtr = (uint8_t*)m_ptr + pageSize * targetPage; 91df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez *targetPtr = dummy; 92df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez } 93df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez void benchLinearRead(unsigned int j) { 94df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez uint8_t *targetPtr = (uint8_t*)m_ptr + pageSize * j; 95df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez dummy += *targetPtr; 96df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez } 97df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez void benchLinearWrite(unsigned int j) { 98df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez uint8_t *targetPtr = (uint8_t*)m_ptr + pageSize * j; 99df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez *targetPtr = dummy; 1006e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 1016e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews void dropCache() { 1026e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews int ret1 = msync(m_ptr, m_size, MS_SYNC | MS_INVALIDATE); 1036e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews madvise(m_ptr, m_size, MADV_DONTNEED); 1046e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews (void)ret1; 1056e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 1066e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews ~FileMap() { 1076e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews if (m_ptr) 1086e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews munmap(m_ptr, m_size); 1096e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews } 1106e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews 1116e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews}; 1126e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews 113df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprezstatic void benchRandomRead(benchmark::State& state) { 114df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez FileMap file{"/data/local/tmp/mmap_test", fsize}; 115df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez while (state.KeepRunning()) { 116df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez unsigned int targetPage = rand() % pagesTotal; 117df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez file.benchRandomRead(targetPage); 1187d20a66002e9a42face7a331d8a72facaddab0faTodd Kjos } 119df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez state.SetBytesProcessed(state.iterations() * pageSize); 120df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez} 121df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien DesprezBENCHMARK(benchRandomRead); 1227d20a66002e9a42face7a331d8a72facaddab0faTodd Kjos 123df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprezstatic void benchRandomWrite(benchmark::State& state) { 124df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez FileMap file{"/data/local/tmp/mmap_test", fsize}; 125df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez while (state.KeepRunning()) { 126df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez unsigned int targetPage = rand() % pagesTotal; 127df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez file.benchRandomWrite(targetPage); 1287d20a66002e9a42face7a331d8a72facaddab0faTodd Kjos } 129df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez state.SetBytesProcessed(state.iterations() * pageSize); 130df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez} 131df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien DesprezBENCHMARK(benchRandomWrite); 1327d20a66002e9a42face7a331d8a72facaddab0faTodd Kjos 133df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprezstatic void benchLinearRead(benchmark::State& state) { 134df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez FileMap file{"/data/local/tmp/mmap_test", fsize}; 135df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez unsigned int j = 0; 136df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez while (state.KeepRunning()) { 137df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez file.benchLinearRead(j); 138df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez j = (j + 1) % pagesTotal; 139df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez } 140df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez state.SetBytesProcessed(state.iterations() * pageSize); 141df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez} 142df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien DesprezBENCHMARK(benchLinearRead); 143df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez 144df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprezstatic void benchLinearWrite(benchmark::State& state) { 145df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez FileMap file{"/data/local/tmp/mmap_test", fsize}; 146df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez unsigned int j = 0; 147df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez while (state.KeepRunning()) { 148df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez file.benchLinearWrite(j); 149df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez j = (j + 1) % pagesTotal; 150df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez } 151df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez state.SetBytesProcessed(state.iterations() * pageSize); 1526e61ea96f3d9765dd9cbf4fa248d90b856c5412aRiley Andrews} 153df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien DesprezBENCHMARK(benchLinearWrite); 154df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien Desprez 155df7cd654309bb90fe83fb823ff5c4f83c2a4afd0Julien DesprezBENCHMARK_MAIN() 156