#include #include #include #include #include #include #include #include #include #include #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) unsigned long long monotonic_timer() { struct timespec time; if (clock_gettime(CLOCK_MONOTONIC, &time)) { handle_error("clock_gettime"); } return time.tv_sec * 1000000000ULL + time.tv_nsec; } void measure_shared_anon_mmap(size_t size) { unsigned long long t0, t_mmap, t_write, t_close, t_munmap; t0 = monotonic_timer(); char* data = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (!data) { handle_error("mmap"); } t_mmap = monotonic_timer(); for (size_t i = 0; i < size; i += 4096) { // write something in all pages data[i] = 'x'; } t_write = monotonic_timer(); // no close because we did't open a file t_close = monotonic_timer(); munmap(data, size); t_munmap = monotonic_timer(); setlocale(LC_NUMERIC, ""); printf("mmap time %'15lld ns\n", t_mmap - t0); printf("write time %'15lld ns\n", t_write - t_mmap); printf("munmap time %'15lld ns\n", t_munmap - t_close); printf("--\n"); } void measure_private_anon_mmap(size_t size) { unsigned long long t0, t_mmap, t_write, t_close, t_munmap; t0 = monotonic_timer(); char* data = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (!data) { handle_error("mmap"); } t_mmap = monotonic_timer(); for (size_t i = 0; i < size; i += 4096) { // write something in all pages data[i] = 'x'; } t_write = monotonic_timer(); // no close because we did't open a file t_close = monotonic_timer(); munmap(data, size); t_munmap = monotonic_timer(); setlocale(LC_NUMERIC, ""); printf("mmap time %'15lld ns\n", t_mmap - t0); printf("write time %'15lld ns\n", t_write - t_mmap); printf("munmap time %'15lld ns\n", t_munmap - t_close); printf("--\n"); } void measure_shm_mmap(size_t size) { unsigned long long t0, t_mmap, t_write, t_close, t_munmap; char* name = "/my-shm-object"; shm_unlink(name); // ignore errors t0 = monotonic_timer(); int shm = shm_open(name, O_RDWR|O_CREAT|O_EXCL, 0); if (shm < 0) { handle_error("shm_open"); } if (ftruncate(shm, size)) { handle_error("ftruncate"); } char* data = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shm, 0); if (!data) { handle_error("mmap"); } t_mmap = monotonic_timer(); for (size_t i = 0; i < size; i += 4096) { // write something in all pages data[i] = 'x'; } t_write = monotonic_timer(); close(shm); t_close = monotonic_timer(); munmap(data, size); t_munmap = monotonic_timer(); setlocale(LC_NUMERIC, ""); printf("mmap time %'15lld ns\n", t_mmap - t0); printf("write time %'15lld ns\n", t_write - t_mmap); printf("close time %'15lld ns\n", t_close - t_write); printf("munmap time %'15lld ns\n", t_munmap - t_close); printf("--\n"); } void bench_round(size_t size) { printf("shared anon mmap %lu bytes\n", size); measure_shared_anon_mmap(size); printf("private anon mmap %lu bytes\n", size); measure_private_anon_mmap(size); printf("posix shm + mmap %lu bytes\n", size); measure_shm_mmap(size); printf("\n"); } int main(int argc, char** argv) { bench_round(1024 * 1024); bench_round(128 * 1024 * 1024); bench_round(1024 * 1024 * 1024); }