Skip to content

Instantly share code, notes, and snippets.

@saagarjha
Created September 29, 2023 10:42
Show Gist options
  • Save saagarjha/1a82fddb67f5870525e104cb2f5454e9 to your computer and use it in GitHub Desktop.
Save saagarjha/1a82fddb67f5870525e104cb2f5454e9 to your computer and use it in GitHub Desktop.
Test whether mmap or read is faster on your computer
// As seen on:
// https://federated.saagarjha.com/notice/AaEMQpJBSbxhLyxYzg
// https://twitter.com/_saagarjha/status/1707423903969341949
// Compiling: gcc mmap_vs_read.c -O3 -o mmap_vs_read
// Usage: ./mmap_vs_read <bigfile> <mmap|read>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
unsigned char hash_buffer(unsigned char *buffer, size_t size) {
unsigned char hash = 0;
while (size--) {
hash ^= *buffer++;
}
return hash;
}
unsigned char test_read(int fd) {
unsigned char hash = 0;
size_t buffer_size = sysconf(_SC_PAGESIZE) * 16;
unsigned char *buffer = malloc(buffer_size);
ssize_t size = 0;
while (size = read(fd, buffer, buffer_size), size > 0) {
hash ^= hash_buffer(buffer, size);
}
return hash;
}
unsigned char test_mmap(int fd) {
off_t size = lseek(fd, 0, SEEK_END);
unsigned char *buffer = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
return hash_buffer(buffer, size);
}
int main(int argc, char **argv) {
int fd = open(*++argv, O_RDONLY);
char *choice = *++argv;
if (!choice) {
return EXIT_FAILURE;
} else if (!strcmp(choice, "read")) {
return test_read(fd);
} else if (!strcmp(choice, "mmap")) {
return test_mmap(fd);
} else {
return EXIT_FAILURE;
}
}
@kithrup
Copy link

kithrup commented Sep 29, 2023

And on the big FreeBSD system:

% repeat 5 time ./tperf ./freenas-boot.zfs.gz read
4.899u 1.149s 0:06.04 99.8%	5+168k 0+0io 0pf+0w
4.913u 1.275s 0:06.18 100.0%	5+167k 0+0io 0pf+0w
4.721u 1.416s 0:06.13 100.0%	5+167k 0+0io 0pf+0w
4.940u 1.189s 0:06.13 99.8%	5+167k 0+0io 0pf+0w
4.950u 1.188s 0:06.13 100.0%	5+167k 0+0io 0pf+0w
% repeat 5 time ./tperf ./freenas-boot.zfs.gz mmap
5.526u 1.637s 0:07.16 99.8%	5+168k 0+0io 0pf+0w
5.647u 1.535s 0:07.18 99.8%	5+167k 0+0io 0pf+0w
5.576u 1.575s 0:07.15 99.8%	5+167k 0+0io 0pf+0w
5.593u 1.551s 0:07.14 100.0%	5+167k 0+0io 0pf+0w
5.397u 1.762s 0:07.15 100.0%	5+168k 0+0io 0pf+0w

The big Mac and FreeBSD systems each have hundreds of gigabytes of RAM, and all three systems are SSD-only. (However: on the big FreeSBD system, I used /tmp which is tmpfs; on the smaller one, which doesn't have as much RAM, the test file was on a ZFS dataset.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment