Last active
November 17, 2020 17:03
-
-
Save bjacob/bf4122719016384e3c297a06e60934a5 to your computer and use it in GitHub Desktop.
test program to mmap a file and read it and measure page faults.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/mman.h> | |
#include <sys/time.h> | |
#include <sys/resource.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <cstdio> | |
#include <cstdint> | |
#include <cstdlib> | |
#include <cstring> | |
int main(int argc, char* argv[]) { | |
if (argc != 3) { | |
fprintf(stderr, "usage: %s <file_to_read> method\n", argv[0]); | |
fprintf(stderr, "where method can be mmap or read\n"); | |
exit(EXIT_FAILURE); | |
} | |
const char* filename = argv[1]; | |
int fd = open(filename, O_RDONLY); | |
if (fd == -1) { | |
fprintf(stderr, "failed to open %s for read\n", filename); | |
exit(EXIT_FAILURE); | |
} | |
struct stat s; | |
if (fstat(fd, &s) == -1) { | |
fprintf(stderr, "failed to stat %s\n", filename); | |
exit(EXIT_FAILURE); | |
} | |
const int page_size = sysconf(_SC_PAGESIZE); | |
printf("page size in bytes: %d\n", page_size); | |
std::size_t size = s.st_size & ~(page_size - 1); | |
printf("file %s has length %llu bytes (rounded down to page size)\n", filename, size); | |
const char* data_char; | |
if (!strcmp(argv[2], "mmap")) { | |
const void* mapping = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0); | |
if (mapping == MAP_FAILED) { | |
fprintf(stderr, "failed to map %s\n", filename); | |
exit(EXIT_FAILURE); | |
} | |
data_char = static_cast<const char*>(mapping); | |
} else if (!strcmp(argv[2], "read")) { | |
void *heap_block; | |
posix_memalign(&heap_block, page_size, size); | |
std::size_t bytes_read = 0; | |
char* buf = static_cast<char*>(heap_block); | |
while (bytes_read < size) { | |
std::size_t n = read(fd, buf, size - bytes_read); | |
buf += n; | |
bytes_read += n; | |
} | |
data_char = static_cast<const char*>(heap_block); | |
} else { | |
fprintf(stderr, "method %s did not match either mmap or read\n", argv[2]); | |
} | |
std::uint64_t dumb_hash = 0; | |
for (std::size_t i = 0; i < size; i += 4 * sizeof(std::uint64_t)) { | |
const std::uint64_t* data = reinterpret_cast<const std::uint64_t*>(data_char + i); | |
dumb_hash ^= data[0]; | |
dumb_hash ^= data[1]; | |
dumb_hash ^= data[2]; | |
dumb_hash ^= data[3]; | |
} | |
printf("dumb_hash = %llx\n", dumb_hash); | |
struct rusage usage; | |
getrusage(RUSAGE_SELF, &usage); | |
printf("bytes read: %llu\n", size); | |
printf("pages read: %llu\n", size / page_size); | |
printf("minor page faults: %llu\n", usage.ru_minflt); | |
printf("major page faults: %llu\n", usage.ru_majflt); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment