1 /* A simple file system workload generator.
3 * Reads and writes a number of files in the current working directory.
5 * Command-line arguments:
8 * Write fraction (0.0 - 1.0)
10 * Benchmark duration (seconds)
21 #include <sys/types.h>
25 int opt_filesize, opt_filecount, opt_threads, opt_duration;
26 double opt_writeratio;
32 int read_count, write_count;
33 int64_t read_time, write_time;
36 static int64_t start_time;
38 #define MAX_THREADS 128
39 struct thread_state threads[MAX_THREADS];
45 if (clock_gettime(CLOCK_REALTIME, &time) != 0) {
46 perror("clock_gettime");
50 return (int64_t)(time.tv_sec) * 1000000000 + time.tv_nsec;
53 int get_random(int range)
55 return random() % range;
58 void sleep_micros(int duration)
64 req.tv_sec = duration / 1000000;
65 req.tv_nsec = (duration % 1000000) * 1000;
67 while (nanosleep(&req, &req) < 0 && errno == EINTR)
74 FILE *f = fopen("writetest", "wb");
81 for (int i = 0; i < 16; i++) {
85 fwrite(buf, 1, sizeof(buf), f);
88 printf("Pass %d: Time = %"PRIi64"\n", i, end - start);
93 void benchmark_op(struct thread_state *ts)
100 sprintf(filename, "t%d/%d", ts->thread_num, get_random(opt_filecount));
102 double r = get_random(1000000) / 1e6;
104 if (r >= opt_writeratio) {
106 FILE *f = fopen(filename, "rb");
113 while (fread(buf, 1, sizeof(buf), f) > 0) { }
117 pthread_mutex_lock(&ts->lock);
119 ts->read_time += (end - start);
120 pthread_mutex_unlock(&ts->lock);
123 FILE *f = fopen(filename, "wb");
130 int bytes_left = opt_filesize;
131 while (bytes_left > 0) {
132 size_t written = fwrite(buf, 1,
133 bytes_left < sizeof(buf)
134 ? bytes_left : sizeof(buf),
138 bytes_left -= written;
143 pthread_mutex_lock(&ts->lock);
145 ts->write_time += (end - start);
146 pthread_mutex_unlock(&ts->lock);
150 void *benchmark_thread(void *arg)
152 struct thread_state *ts = (struct thread_state *)arg;
156 //sleep_micros(100000);
162 void launch_thread(int i)
164 memset(&threads[i], 0, sizeof(struct thread_state));
165 threads[i].thread_num = i;
166 pthread_mutex_init(&threads[i].lock, NULL);
167 printf("Launching thread %d...\n", i);
168 if (pthread_create(&threads[i].thread, NULL, benchmark_thread, &threads[i]) != 0) {
169 fprintf(stderr, "Error launching thread!\n");
174 void wait_thread(int n)
177 pthread_join(threads[n].thread, &result);
180 void reset_stats(int print)
182 int read_count = 0, write_count = 0;
183 int64_t read_time = 0, write_time = 0;
185 for (int i = 0; i < opt_threads; i++) {
186 pthread_mutex_lock(&threads[i].lock);
187 read_count += threads[i].read_count;
188 write_count += threads[i].write_count;
189 read_time += threads[i].read_time;
190 write_time += threads[i].write_time;
191 threads[i].read_count = threads[i].write_count = 0;
192 threads[i].read_time = threads[i].write_time = 0;
193 pthread_mutex_unlock(&threads[i].lock);
197 printf("Reads: %d operations, %f average latency\n",
198 read_count, read_time / 1e9 / read_count);
199 printf("Writes: %d operations, %f average latency\n",
200 write_count, write_time / 1e9 / write_count);
204 int main(int argc, char *argv[])
207 fprintf(stderr, "Usage: TODO\n");
211 opt_filesize = atoi(argv[1]);
212 opt_filecount = atoi(argv[2]);
213 opt_writeratio = atof(argv[3]);
214 opt_threads = atoi(argv[4]);
215 opt_duration = atoi(argv[5]);
219 start_time = now_hires();
220 printf("Testing with %d threads\n", opt_threads);
222 for (int i = 0; i < opt_threads; i++) {
226 /* Warm up phase: run for half the time but do not keep statistics */
227 sleep_micros(opt_duration * 1000000 / 2);
230 /* Benchmark phase: run for half the time and print summary */
231 sleep_micros(opt_duration * 1000000 / 2);