diff options
author | Mohan Srinivasan <srmohan@google.com> | 2017-01-19 21:27:36 +0000 |
---|---|---|
committer | Mohan Srinivasan <srmohan@google.com> | 2017-01-19 21:27:36 +0000 |
commit | f2f5b6165a4b107f79a7e709f63fb66118a72477 (patch) | |
tree | 1efc2c2685ca028f31e20efce1fcfdec9297237c /ioshark/ioshark_bench.c | |
parent | a5dc6d6fcab8dfe719c437e8a9111ba962df1c15 (diff) | |
download | extras-f2f5b6165a4b107f79a7e709f63fb66118a72477.tar.gz |
Revert "ioshark: A Repeatable Application Workload Based Storage Benchmark." (Broke the MacOS build - will commit after I test that this builds for MacOS).
This reverts commit a5dc6d6fcab8dfe719c437e8a9111ba962df1c15.
Change-Id: I53bc71eeb1bc3ad7706baae589cef8a80ef94c35
Diffstat (limited to 'ioshark/ioshark_bench.c')
-rw-r--r-- | ioshark/ioshark_bench.c | 739 |
1 files changed, 0 insertions, 739 deletions
diff --git a/ioshark/ioshark_bench.c b/ioshark/ioshark_bench.c deleted file mode 100644 index 5b19d2a9..00000000 --- a/ioshark/ioshark_bench.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#include <sys/syscall.h> -#include <stdlib.h> -#include <string.h> -#include <pthread.h> -#include <sys/stat.h> -#include <sys/errno.h> -#include <fcntl.h> -#include <string.h> -#include <assert.h> -#include <pthread.h> -#include <sys/statfs.h> -#include "ioshark.h" -#define IOSHARK_MAIN -#include "ioshark_bench.h" - -char *progname; - -#define MAX_INPUT_FILES 1024 -#define MAX_THREADS 1024 - -struct thread_state_s { - char *filename; - FILE *fp; - int num_files; - void *db_handle; -}; - -struct thread_state_s thread_state[MAX_INPUT_FILES]; -int num_input_files = 0; -int next_input_file; - -pthread_t tid[MAX_THREADS]; - -/* - * Global options - */ -int do_delay = 0; -int verbose = 0; - -#if 0 -static long gettid() -{ - return syscall(__NR_gettid); -} -#endif - -void usage() -{ - fprintf(stderr, "%s [-d preserve_delays] [-n num_iterations] [-t num_threads] <list of parsed input files>\n", - progname); - exit(EXIT_FAILURE); -} - -pthread_mutex_t time_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t stats_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t work_mutex = PTHREAD_MUTEX_INITIALIZER; -struct timeval aggregate_file_create_time; -struct timeval debug_file_create_time; -struct timeval aggregate_file_remove_time; -struct timeval aggregate_IO_time; -struct timeval aggregate_delay_time; - -u_int64_t aggr_op_counts[IOSHARK_MAX_FILE_OP]; -struct rw_bytes_s aggr_io_rw_bytes; -struct rw_bytes_s aggr_create_rw_bytes; - -/* - * Locking needed here because aggregate_delay_time is updated - * from multiple threads concurrently. - */ -static void -update_time(struct timeval *aggr_time, - struct timeval *delta_time) -{ - struct timeval tmp; - - pthread_mutex_lock(&time_mutex); - timeradd(aggr_time, delta_time, &tmp); - *aggr_time = tmp; - pthread_mutex_unlock(&time_mutex); -} - -static void -update_op_counts(u_int64_t *op_counts) -{ - int i; - - pthread_mutex_lock(&stats_mutex); - for (i = IOSHARK_LSEEK ; i < IOSHARK_MAX_FILE_OP ; i++) - aggr_op_counts[i] += op_counts[i]; - pthread_mutex_unlock(&stats_mutex); -} - -static void -update_byte_counts(struct rw_bytes_s *dest, struct rw_bytes_s *delta) -{ - pthread_mutex_lock(&stats_mutex); - dest->bytes_read += delta->bytes_read; - dest->bytes_written += delta->bytes_written; - pthread_mutex_unlock(&stats_mutex); -} - -static int work_next_file; -static int work_num_files; - -void -init_work(int next_file, int num_files) -{ - pthread_mutex_lock(&work_mutex); - work_next_file = next_file; - work_num_files = work_next_file + num_files; - pthread_mutex_unlock(&work_mutex); -} - -/* Dole out the next file to work on to the thread */ -static struct thread_state_s * -get_work() -{ - struct thread_state_s *work = NULL; - - pthread_mutex_lock(&work_mutex); - if (work_next_file < work_num_files) - work = &thread_state[work_next_file++]; - pthread_mutex_unlock(&work_mutex); - return work; -} - -static void -create_files(struct thread_state_s *state) -{ - int i; - struct ioshark_file_state file_state; - char path[512]; - void *db_node; - struct rw_bytes_s rw_bytes; - - memset(&rw_bytes, 0, sizeof(struct rw_bytes_s)); - for (i = 0 ; i < state->num_files ; i++) { - if (fread(&file_state, sizeof(struct ioshark_file_state), - 1, state->fp) != 1) { - fprintf(stderr, "%s read error tracefile\n", - progname); - exit(EXIT_FAILURE); - } - sprintf(path, "file.%d.%d", - (int)(state - thread_state), - file_state.fileno); - create_file(path, file_state.size, - &rw_bytes); - db_node = files_db_add_byfileno(state->db_handle, - file_state.fileno); - files_db_update_size(db_node, file_state.size); - files_db_update_filename(db_node, path); - } - update_byte_counts(&aggr_create_rw_bytes, &rw_bytes); -} - -static void -do_one_io(void *db_node, - struct ioshark_file_operation *file_op, - u_int64_t *op_counts, - struct rw_bytes_s *rw_bytes, - char **bufp, int *buflen) -{ - assert(file_op->file_op < IOSHARK_MAX_FILE_OP); - op_counts[file_op->file_op]++; - switch (file_op->file_op) { - int ret; - char *p; - int fd; - - case IOSHARK_LSEEK: - case IOSHARK_LLSEEK: - ret = lseek(files_db_get_fd(db_node), - file_op->lseek_offset, - file_op->lseek_action); - if (ret < 0) { - fprintf(stderr, - "%s: lseek(%s %lu %d) returned error %d\n", - progname, files_db_get_filename(db_node), - file_op->lseek_offset, - file_op->lseek_action, errno); - exit(EXIT_FAILURE); - } - break; - case IOSHARK_PREAD64: - p = get_buf(bufp, buflen, file_op->prw_len, 0); - ret = pread(files_db_get_fd(db_node), p, - file_op->prw_len, file_op->prw_offset); - rw_bytes->bytes_read += file_op->prw_len; - if (ret < 0) { - fprintf(stderr, - "%s: pread(%s %zu %lu) error %d\n", - progname, - files_db_get_filename(db_node), - file_op->prw_len, - file_op->prw_offset, errno); - exit(EXIT_FAILURE); - } - break; - case IOSHARK_PWRITE64: - p = get_buf(bufp, buflen, file_op->prw_len, 1); - ret = pwrite(files_db_get_fd(db_node), p, - file_op->prw_len, file_op->prw_offset); - rw_bytes->bytes_written += file_op->prw_len; - if (ret < 0) { - fprintf(stderr, - "%s: pwrite(%s %zu %lu) error %d\n", - progname, - files_db_get_filename(db_node), - file_op->prw_len, - file_op->prw_offset, errno); - exit(EXIT_FAILURE); - } - break; - case IOSHARK_READ: - p = get_buf(bufp, buflen, file_op->rw_len, 0); - ret = read(files_db_get_fd(db_node), p, - file_op->rw_len); - rw_bytes->bytes_read += file_op->rw_len; - if (ret < 0) { - fprintf(stderr, - "%s: read(%s %zu) error %d\n", - progname, - files_db_get_filename(db_node), - file_op->rw_len, - errno); - exit(EXIT_FAILURE); - } - break; - case IOSHARK_WRITE: - p = get_buf(bufp, buflen, file_op->rw_len, 1); - ret = write(files_db_get_fd(db_node), p, - file_op->rw_len); - rw_bytes->bytes_written += file_op->rw_len; - if (ret < 0) { - fprintf(stderr, - "%s: write(%s %zu) error %d\n", - progname, - files_db_get_filename(db_node), - file_op->rw_len, - errno); - exit(EXIT_FAILURE); - } - break; - case IOSHARK_MMAP: - case IOSHARK_MMAP2: - ioshark_handle_mmap(db_node, file_op, - bufp, buflen, op_counts, - rw_bytes); - break; - case IOSHARK_OPEN: - if (file_op->open_flags & O_CREAT) { - fd = open(files_db_get_filename(db_node), - file_op->open_flags, - file_op->open_mode); - if (fd < 0) { - /* - * EEXIST error acceptable, others are fatal. - * Although we failed to O_CREAT the file (O_EXCL) - * We will force an open of the file before any - * IO. - */ - if (errno == EEXIST) { - return; - } else { - fprintf(stderr, - "%s: O_CREAT open(%s %x %o) error %d\n", - progname, - files_db_get_filename(db_node), - file_op->open_flags, - file_op->open_mode, errno); - exit(EXIT_FAILURE); - } - } - } else { - fd = open(files_db_get_filename(db_node), - file_op->open_flags); - if (fd < 0) { - if (file_op->open_flags & O_DIRECTORY) { - /* O_DIRECTORY open()s should fail */ - return; - } else { - fprintf(stderr, - "%s: open(%s %x) error %d\n", - progname, - files_db_get_filename(db_node), - file_op->open_flags, - errno); - exit(EXIT_FAILURE); - } - } - } - files_db_close_fd(db_node); - files_db_update_fd(db_node, fd); - break; - case IOSHARK_FSYNC: - case IOSHARK_FDATASYNC: - if (file_op->file_op == IOSHARK_FSYNC) { - ret = fsync(files_db_get_fd(db_node)); - if (ret < 0) { - fprintf(stderr, - "%s: fsync(%s) error %d\n", - progname, - files_db_get_filename(db_node), - errno); - exit(EXIT_FAILURE); - } - } else { - ret = fdatasync(files_db_get_fd(db_node)); - if (ret < 0) { - fprintf(stderr, - "%s: fdatasync(%s) error %d\n", - progname, - files_db_get_filename(db_node), - errno); - exit(EXIT_FAILURE); - } - } - break; - case IOSHARK_CLOSE: - ret = close(files_db_get_fd(db_node)); - if (ret < 0) { - fprintf(stderr, - "%s: close(%s) error %d\n", - progname, - files_db_get_filename(db_node), errno); - exit(EXIT_FAILURE); - } - files_db_update_fd(db_node, -1); - break; - default: - fprintf(stderr, "%s: unknown FILE_OP %d\n", - progname, file_op->file_op); - exit(EXIT_FAILURE); - break; - } -} - -static void -do_io(struct thread_state_s *state) -{ - void *db_node; - struct ioshark_header header; - struct ioshark_file_operation file_op; - u_int64_t prev_delay = 0; - int fd; - int i; - char *buf = NULL; - int buflen = 0; - struct timeval total_delay_time; - u_int64_t op_counts[IOSHARK_MAX_FILE_OP]; - struct rw_bytes_s rw_bytes; - - rewind(state->fp); - if (fread(&header, sizeof(struct ioshark_header), 1, state->fp) != 1) { - fprintf(stderr, "%s read error %s\n", - progname, state->filename); - exit(EXIT_FAILURE); - } - /* - * First open and pre-create all the files. Indexed by fileno. - */ - timerclear(&total_delay_time); - memset(&rw_bytes, 0, sizeof(struct rw_bytes_s)); - memset(op_counts, 0, sizeof(op_counts)); - fseek(state->fp, - sizeof(struct ioshark_header) + - header.num_files * sizeof(struct ioshark_file_state), - SEEK_SET); - /* - * Loop over all the IOs, and launch each - */ - for (i = 0 ; i < header.num_io_operations ; i++) { - if (fread(&file_op, sizeof(struct ioshark_file_operation), - 1, state->fp) != 1) { - fprintf(stderr, "%s read error trace.outfile\n", - progname); - exit(EXIT_FAILURE); - } - if (do_delay) { - struct timeval start; - - (void)gettimeofday(&start, (struct timezone *)NULL); - usleep(file_op.delta_us - prev_delay); - update_delta_time(&start, &total_delay_time); - prev_delay = file_op.delta_us; - } - db_node = files_db_lookup_byfileno(state->db_handle, - file_op.fileno); - if (db_node == NULL) { - fprintf(stderr, - "%s Can't lookup fileno %d, fatal error\n", - progname, file_op.fileno); - exit(EXIT_FAILURE); - } - if (file_op.file_op != IOSHARK_OPEN && - files_db_get_fd(db_node) == -1) { - /* - * This is a hack to workaround the fact that we did not - * see an open() for this file until now. open() the file - * O_RDWR, so that we can perform the IO. - */ - fd = open(files_db_get_filename(db_node), O_RDWR); - if (fd < 0) { - fprintf(stderr, "%s: open(%s O_RDWR) error %d\n", - progname, files_db_get_filename(db_node), - errno); - exit(EXIT_FAILURE); - } - files_db_update_fd(db_node, fd); - } - do_one_io(db_node, &file_op, - op_counts, &rw_bytes, &buf, &buflen); - } - files_db_fsync_discard_files(state->db_handle); - files_db_close_files(state->db_handle); - update_time(&aggregate_delay_time, &total_delay_time); - update_op_counts(op_counts); - update_byte_counts(&aggr_io_rw_bytes, &rw_bytes); -} - -void * -io_thread(void *unused __attribute__((unused))) -{ - struct thread_state_s *state; - - srand(gettid()); - while ((state = get_work())) - do_io(state); - pthread_exit(NULL); - return(NULL); -} - -static void -do_create(struct thread_state_s *state) -{ - struct ioshark_header header; - - if (fread(&header, sizeof(struct ioshark_header), 1, state->fp) != 1) { - fprintf(stderr, "%s read error %s\n", - progname, state->filename); - exit(EXIT_FAILURE); - } - state->num_files = header.num_files; - state->db_handle = files_db_create_handle(); - create_files(state); -} - -void * -create_files_thread(void *unused __attribute__((unused))) -{ - struct thread_state_s *state; - - while ((state = get_work())) - do_create(state); - pthread_exit(NULL); - return(NULL); -} - -int -get_start_end(int *start_ix) -{ - int i, j, ret_numfiles; - u_int64_t free_fs_bytes; - char *infile; - FILE *fp; - struct ioshark_header header; - struct ioshark_file_state file_state; - struct statfs fsstat; - static int fssize_clamp_next_index = 0; - static int chunk = 0; - - if (fssize_clamp_next_index == num_input_files) - return 0; - if (statfs("/data/local/tmp", &fsstat) < 0) { - fprintf(stderr, "%s: Can't statfs /data/local/tmp\n", - progname); - exit(EXIT_FAILURE); - } - free_fs_bytes = (fsstat.f_bavail * fsstat.f_bsize) * 9 /10; - for (i = fssize_clamp_next_index; i < num_input_files; i++) { - infile = thread_state[i].filename; - fp = fopen(infile, "r"); - if (fp == NULL) { - fprintf(stderr, "%s: Can't open %s\n", - progname, infile); - exit(EXIT_FAILURE); - } - if (fread(&header, sizeof(struct ioshark_header), - 1, fp) != 1) { - fprintf(stderr, "%s read error %s\n", - progname, infile); - exit(EXIT_FAILURE); - } - for (j = 0 ; j < header.num_files ; j++) { - if (fread(&file_state, sizeof(struct ioshark_file_state), - 1, fp) != 1) { - fprintf(stderr, "%s read error tracefile\n", - progname); - exit(EXIT_FAILURE); - } - if (file_state.size > free_fs_bytes) { - fclose(fp); - goto out; - } - free_fs_bytes -= file_state.size; - } - fclose(fp); - } -out: - if (verbose) { - if (chunk > 0 || i < num_input_files) { - printf("Breaking up input files, Chunk %d: %d to %d\n", - chunk++, fssize_clamp_next_index, i - 1); - } else { - printf("Entire Dataset fits start = %d to %d, free_bytes = %ju\n", - fssize_clamp_next_index, - i - fssize_clamp_next_index, - free_fs_bytes); - } - } - *start_ix = fssize_clamp_next_index; - ret_numfiles = i - fssize_clamp_next_index; - fssize_clamp_next_index = i; - return ret_numfiles; -} - -int -ioshark_pthread_create(pthread_t *tidp, void *(*start_routine)(void *)) -{ - pthread_attr_t attr; - - pthread_attr_init(&attr); - pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); - pthread_attr_setstacksize(&attr, (size_t)(1024*1024)); - return pthread_create(tidp, &attr, start_routine, (void *)NULL); -} - -void -wait_for_threads(int num_threads) -{ - int i; - - for (i = 0; i < num_threads; i++) { - pthread_join(tid[i], NULL); - tid[i] = 0; - } -} - -int -main(int argc, char **argv) -{ - int i; - FILE *fp; - struct stat st; - char *infile; - int num_threads = 0; - int num_iterations = 1; - int c; - int num_files, start_file; - struct thread_state_s *state; - - progname = argv[0]; - while ((c = getopt(argc, argv, "dn:t:v")) != EOF) { - switch (c) { - case 'd': - do_delay = 1; - break; - case 'n': - num_iterations = atoi(optarg); - break; - case 't': - num_threads = atoi(optarg); - break; - case 'v': - verbose = 1; - break; - default: - usage(); - } - } - - if (num_threads > MAX_THREADS) - usage(); - - if (optind == argc) - usage(); - - for (i = optind; i < argc; i++) { - infile = argv[i]; - if (stat(infile, &st) < 0) { - fprintf(stderr, "%s: Can't stat %s\n", - progname, infile); - exit(EXIT_FAILURE); - continue; - } - if (st.st_size == 0) { - fprintf(stderr, "%s: Empty file %s\n", - progname, infile); - continue; - } - fp = fopen(infile, "r"); - if (fp == NULL) { - fprintf(stderr, "%s: Can't open %s\n", - progname, infile); - continue; - } - thread_state[num_input_files].filename = infile; - thread_state[num_input_files].fp = fp; - num_input_files++; - } - - if (num_input_files == 0) { - exit(EXIT_SUCCESS); - } - if (verbose) { - printf("Total Input Files = %d\n", num_input_files); - printf("Num Iterations = %d\n", num_iterations); - } - timerclear(&aggregate_file_create_time); - timerclear(&aggregate_file_remove_time); - timerclear(&aggregate_IO_time); - - capture_util_state_before(); - - /* - * We pre-create the files that we need once and then we - * loop around N times doing IOs on the pre-created files. - * - * get_start_end() breaks up the total work here to make sure - * that all the files we need to pre-create fit into the - * available space in /data/local/tmp (hardcoded for now). - * - * If it won't fit, then we do several sweeps. - */ - while ((num_files = get_start_end(&start_file))) { - struct timeval time_for_pass; - - /* Create files once */ - printf("Doing Pre-creation of Files\n"); - if (num_threads == 0 || num_threads > num_files) - num_threads = num_files; - (void)system("echo 3 > /proc/sys/vm/drop_caches"); - init_work(start_file, num_files); - (void)gettimeofday(&time_for_pass, - (struct timezone *)NULL); - for (i = 0; i < num_threads; i++) { - if (ioshark_pthread_create(&(tid[i]), - create_files_thread)) { - fprintf(stderr, - "%s: Can't create creator thread %d\n", - progname, i); - exit(EXIT_FAILURE); - } - } - wait_for_threads(num_threads); - update_delta_time(&time_for_pass, &aggregate_file_create_time); - - /* Do the IOs N times */ - for (i = 0 ; i < num_iterations ; i++) { - (void)system("echo 3 > /proc/sys/vm/drop_caches"); - if (num_iterations > 1) - printf("Starting Test. Iteration %d...\n", - i); - else - printf("Starting Test...\n"); - init_work(start_file, num_files); - (void)gettimeofday(&time_for_pass, - (struct timezone *)NULL); - for (c = 0; c < num_threads; c++) { - if (ioshark_pthread_create(&(tid[c]), - io_thread)) { - fprintf(stderr, - "%s: Can't create thread %d\n", - progname, c); - exit(EXIT_FAILURE); - } - } - wait_for_threads(num_threads); - update_delta_time(&time_for_pass, - &aggregate_IO_time); - } - - /* - * We are done with the N iterations of IO. - * Destroy the files we pre-created. - */ - init_work(start_file, num_files); - while ((state = get_work())) { - struct timeval start; - - (void)gettimeofday(&start, (struct timezone *)NULL); - files_db_unlink_files(state->db_handle); - update_delta_time(&start, &aggregate_file_remove_time); - files_db_free_memory(state->db_handle); - } - } - printf("Total Creation time = %ju.%ju (msecs.usecs)\n", - get_msecs(&aggregate_file_create_time), - get_usecs(&aggregate_file_create_time)); - printf("Total Remove time = %ju.%ju (msecs.usecs)\n", - get_msecs(&aggregate_file_remove_time), - get_usecs(&aggregate_file_remove_time)); - if (do_delay) - printf("Total delay time = %ju.%ju (msecs.usecs)\n", - get_msecs(&aggregate_delay_time), - get_usecs(&aggregate_delay_time)); - printf("Total Test (IO) time = %ju.%ju (msecs.usecs)\n", - get_msecs(&aggregate_IO_time), - get_usecs(&aggregate_IO_time)); - if (verbose) - print_bytes("Upfront File Creation bytes", - &aggr_create_rw_bytes); - print_bytes("Total Test (IO) bytes", &aggr_io_rw_bytes); - if (verbose) - print_op_stats(aggr_op_counts); - report_cpu_disk_util(); -} |