2 simulate IO and thread pattern in ntap sio test
4 Copyright (C) Andrew Tridgell <tridge@samba.org> 2007
6 Released under the GNU GPL version 2 or later
10 #define _FILE_OFFSET_BITS 64
11 #define _LARGEFILE64_SOURCE
19 #include <sys/types.h>
30 static size_t block_size = 8192;
31 static off_t file_size = 1024*1024*(1024LL);
32 static unsigned num_threads = 1;
33 static const char *fname;
34 static volatile unsigned *io_count;
35 static volatile int run_finished;
36 static unsigned runtime = 20;
38 static bool direct_io;
39 static int flush_blocks;
45 static int open_file(int id)
47 unsigned flags = O_RDWR|O_CREAT|O_LARGEFILE;
51 if (sync_io) flags |= O_SYNC;
52 if (direct_io) flags |= O_DIRECT;
53 if (id != -1 && strchr(fname, '%')) {
54 asprintf(&name, fname, id);
58 fd = open(name, flags, 0644);
67 static void run_child(int id)
69 unsigned num_blocks = file_size / block_size;
73 if (!one_fd && !reopen) {
79 buf = malloc(block_size);
80 memset(buf, 1, block_size);
82 srandom(id ^ random());
84 while (!run_finished) {
85 unsigned offset = random() % num_blocks;
89 if (pwrite(fd, buf, block_size, offset*(off_t)block_size) != block_size) {
91 printf("pwrite failed!\n");
95 if (flush_blocks && io_count[id] % flush_blocks == 0) {
108 create a thread with initial function fn(private)
110 static pthread_t thread_start(void (*fn)(int), int id)
113 pthread_attr_t thread_attr;
115 typedef void *(*thread_fn_t)(void *);
116 pthread_attr_init(&thread_attr);
117 pthread_attr_setdetachstate(&thread_attr, 0);
118 rc = pthread_create(&thread_id, &thread_attr, (thread_fn_t)fn, (void *)id);
119 pthread_attr_destroy(&thread_attr);
122 fprintf(stderr,"Thread create failed for id %d\n", id);
129 /* wait for a thread to exit */
130 static int thread_join(pthread_t id)
132 return pthread_join(id, NULL);
136 static void run_test(void)
141 unsigned warmup_count=0;
144 tids = calloc(num_threads, sizeof(pthread_t));
145 io_count = calloc(num_threads, sizeof(unsigned));
148 shared_fd = open_file(-1);
152 for (i=0;i<num_threads;i++) {
153 tids[i] = thread_start(run_child, i);
158 time_t t = time(NULL);
166 for (i=0;i<num_threads;i++) {
167 unsigned count = io_count[i];
168 printf("%6u ", count);
174 printf(" total: %6u ", total);
175 if (started != 0 && started != t) {
176 printf(" %3u seconds %.0f kbytes/s\n",
177 (unsigned)(t - started),
178 block_size*(total-warmup_count)/(1024.0*(t-started)));
184 printf("Starting run\n");
185 warmup_count = total;
187 if (time(NULL) - started >= runtime) {
194 printf("Run finished - cleaning up\n");
195 for (i=0;i<num_threads;i++) {
196 thread_join(tids[i]);
197 printf("finished thread %d\n", i);
200 printf("Throughput %.0f kbytes/s\n",
201 block_size*(total-warmup_count)/(1024.0*runtime));
204 static void usage(void)
206 printf("Usage: threadio <options> <filename>\n");
207 printf("Options:\n");
208 printf(" -b <size> block size\n");
209 printf(" -f <size> file size\n");
210 printf(" -n <number> number of threads\n");
211 printf(" -t <time> runtime in seconds\n");
212 printf(" -F <numios> fsync every numios blocks per thread\n");
213 printf(" -S use O_SYNC on open\n");
214 printf(" -D use O_DIRECT on open\n");
215 printf(" -R reopen the file on every write\n");
216 printf(" -1 use one file descriptor for all threads\n");
217 printf("\nNote: when not using -1, filename may contain %%d for thread id\n");
221 int main(int argc, char * const argv[])
227 while ((opt = getopt(argc, argv, "b:f:n:t:1F:SDsR")) != -1) {
230 block_size = strtoul(optarg, NULL, 0);
233 file_size = strtoull(optarg, NULL, 0);
236 num_threads = strtoul(optarg, NULL, 0);
239 runtime = strtoul(optarg, NULL, 0);
248 flush_blocks = strtoul(optarg, NULL, 0);
257 printf("Invalid option '%c'\n", opt);