Skip to content

Instantly share code, notes, and snippets.

@bjacob
Last active November 17, 2020 17:03
Show Gist options
  • Save bjacob/bf4122719016384e3c297a06e60934a5 to your computer and use it in GitHub Desktop.
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.
#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