summaryrefslogtreecommitdiffstats
path: root/directio_paging_speed.c
diff options
context:
space:
mode:
Diffstat (limited to 'directio_paging_speed.c')
-rw-r--r--directio_paging_speed.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/directio_paging_speed.c b/directio_paging_speed.c
index b0a01d3..9dd6598 100644
--- a/directio_paging_speed.c
+++ b/directio_paging_speed.c
@@ -1,19 +1,34 @@
1/**
2 * Copyright 2022 Joshua Bakita
3 * This program clocks how long it takes to read, and write, a 1GiB buffer via
4 * Linux direct I/O.
5 *
6 * More precisely, this program clocks:
7 * write(random_buffer);
8 * free(random_buffer);
9 * for writing data via direct I/O, and
10 * malloc(big_buffer);
11 * read(big_buffer);
12 * for reading in data via direct I/O. `random_buffer` is a preinitialized 1GiB
13 * buffer of random non-zero bytes.
14 */
1#define _GNU_SOURCE 15#define _GNU_SOURCE
2 16
3#include <sys/mman.h>
4#include <sys/types.h>
5#include <sys/stat.h>
6#include <fcntl.h> 17#include <fcntl.h>
7#include <stdio.h>
8#include <stdint.h> 18#include <stdint.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <sys/mman.h>
22#include <sys/stat.h>
23#include <sys/types.h>
9#include <time.h> 24#include <time.h>
10#include <unistd.h> 25#include <unistd.h>
11#include <stdlib.h>
12 26
13#define GiB 1024l*1024l*1024l 27#define GiB 1024l*1024l*1024l
14#define s2ns(s) ((s)*1000l*1000l*1000l) 28#define s2ns(s) ((s)*1000l*1000l*1000l)
15#define ns2us(ns) ((ns)/1000l) 29#define ns2us(ns) ((ns)/1000l)
16#define PAGED_FILE "/dev/nvme0n1" 30#define PAGED_FILE "/dev/nvme0n1"
31#define CLEAR_PAGECACHE_DENTRIES_INODES "3"
17int max(int x, int y) {return x > y ? x : y;} 32int max(int x, int y) {return x > y ? x : y;}
18 33
19// Original function from copy_only.cu 34// Original function from copy_only.cu
@@ -31,16 +46,24 @@ uint64_t count_zero(char* buf, uint64_t buf_len) {
31 return num_zeros; 46 return num_zeros;
32} 47}
33 48
49// Subtract first parameter from second parameter. Return as nanoseconds.
34long time_diff_ns(struct timespec start, struct timespec stop) { 50long time_diff_ns(struct timespec start, struct timespec stop) {
35 return (s2ns(stop.tv_sec) + stop.tv_nsec) - (s2ns(start.tv_sec) + start.tv_nsec); 51 return (s2ns(stop.tv_sec) + stop.tv_nsec) - (s2ns(start.tv_sec) + start.tv_nsec);
36} 52}
37 53
38int main(int argc, char **argv) { 54int main(int argc, char **argv) {
39 struct timespec out_start, out_stop, in_start, in_stop; 55 struct timespec out_start, out_stop, in_start, in_stop;
40 int iters = 1; 56 int iters, res;
41 int res; 57
42 if (argc > 1) 58 if (argc != 2 || argv[1][0] == '-') {
43 iters = atoi(argv[1]); 59 fprintf(stderr, "Usage: %s <number of iterations>\n", argv[0]);
60 return 1;
61 }
62 iters = atoi(argv[1]);
63
64 // If output is redirected, add comment with source details
65 if (!isatty(fileno(stdout)))
66 fprintf(stdout, "# Generated by '%s %s'\n", argv[0], argv[1]);
44 67
45 // Needed to allow page cache clearing between iterations 68 // Needed to allow page cache clearing between iterations
46 // Note: Shouldn't be needed with O_DIRECT, but include it just in case 69 // Note: Shouldn't be needed with O_DIRECT, but include it just in case
@@ -49,8 +72,8 @@ int main(int argc, char **argv) {
49 perror("Unable to open /proc/sys/vm/drop_caches"); 72 perror("Unable to open /proc/sys/vm/drop_caches");
50 return 1; 73 return 1;
51 } 74 }
52 char clear_cmd = '3';
53 75
76 // Print table header. One read, one write sample per following row
54 printf("out (us)\tin (us)\n"); 77 printf("out (us)\tin (us)\n");
55 for (int i = 0; i < iters; i++) { 78 for (int i = 0; i < iters; i++) {
56 char *mem_in, *mem_out; 79 char *mem_in, *mem_out;
@@ -60,7 +83,7 @@ int main(int argc, char **argv) {
60 return 1; 83 return 1;
61 } 84 }
62 // Clear page cache 85 // Clear page cache
63 write(clear_fd, &clear_cmd, 1); 86 write(clear_fd, CLEAR_PAGECACHE_DENTRIES_INODES, 1);
64 // Allocate and fill a buffer with random data 87 // Allocate and fill a buffer with random data
65 // Aligned malloc(GiB) basicially 88 // Aligned malloc(GiB) basicially
66 res = posix_memalign((void**)&mem_in, 4096, GiB); 89 res = posix_memalign((void**)&mem_in, 4096, GiB);
@@ -81,7 +104,7 @@ int main(int argc, char **argv) {
81 } 104 }
82 105
83 sleep(1); // Supposedly some other work would happen here 106 sleep(1); // Supposedly some other work would happen here
84 write(clear_fd, &clear_cmd, 1); // Just in case O_DIRECT misbehaves 107 write(clear_fd, CLEAR_PAGECACHE_DENTRIES_INODES, 1); // Just in case O_DIRECT misbehaves
85 res = lseek(fd, 0, SEEK_SET); // Reposition offset 108 res = lseek(fd, 0, SEEK_SET); // Reposition offset
86 if (res == -1) { 109 if (res == -1) {
87 perror("Unable to seek to offset 0 in " PAGED_FILE); 110 perror("Unable to seek to offset 0 in " PAGED_FILE);