Created
September 5, 2014 15:36
-
-
Save itiut/779b3b68ee4441a2316a to your computer and use it in GitHub Desktop.
a prototype of microbenchmark for sequential read
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <fcntl.h> | |
#include <linux/fs.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/ioctl.h> | |
#include <sys/stat.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
inline void xgettimeofday(struct timeval *tv) { | |
if (gettimeofday(tv, NULL) == -1) { | |
perror("gettimeofday(2)"); | |
exit(EXIT_FAILURE); | |
} | |
} | |
double to_f(struct timeval tv) { | |
return tv.tv_sec + tv.tv_usec * 1e-6; | |
} | |
int main(int argc, char *argv[]) { | |
if (argc != 3 && argc != 4) { | |
printf("Usage: %s device block_size [max_count]\n", argv[0]); | |
return 0; | |
} | |
const char *device = argv[1]; | |
const size_t each_bytes = atoi(argv[2]); | |
if (strncmp(device, "/dev/sda", strlen("/dev/sda")) == 0) { | |
printf("You should not read or write /dev/sda*\n"); | |
exit(EXIT_FAILURE); | |
} | |
int fd = open(device, O_RDONLY); | |
if (fd == -1) { | |
perror("open(2)"); | |
exit(EXIT_FAILURE); | |
} | |
unsigned long long sector_size = 0; | |
if (ioctl(fd, BLKSSZGET, §or_size) == -1) { | |
perror("ioctl(2)"); | |
exit(EXIT_FAILURE); | |
} | |
unsigned long long n_of_sectors = 0; | |
if (ioctl(fd, BLKGETSIZE, &n_of_sectors) == -1) { | |
perror("ioctl(2)"); | |
exit(EXIT_FAILURE); | |
} | |
unsigned long long volume = sector_size * n_of_sectors; | |
unsigned long long max_count = (volume / each_bytes) + ((volume % each_bytes == 0) ? 0 : 1); | |
if (argc == 4) { | |
max_count = atoi(argv[3]); | |
} | |
char *buffer = (char *) malloc(each_bytes); | |
struct timeval *tvs = (struct timeval *) calloc(max_count + 1, sizeof(struct timeval)); | |
ssize_t size; | |
unsigned long long count = 0; | |
xgettimeofday(&tvs[count]); | |
for ( ; count < max_count; count++) { | |
if ((size = read(fd, buffer, each_bytes)) <= 0) { | |
break; | |
} | |
xgettimeofday(&tvs[count + 1]); | |
} | |
if (size == -1) { | |
perror("read(2)"); | |
exit(EXIT_FAILURE); | |
} | |
unsigned long long skip = (count > 1000) ? count / 1000 : 1; | |
for (unsigned long long i = skip; i <= count; i += skip) { | |
printf("%lld %f\n", i, to_f(tvs[i]) - to_f(tvs[i - skip])); | |
} | |
double total_size_mb = each_bytes * count * 1e-6; | |
double elapsed_time_sec = to_f(tvs[count]) - to_f(tvs[0]); | |
double throughput_mb_per_sec = total_size_mb / elapsed_time_sec; | |
printf("####################################\n"); | |
printf("# INFO\n"); | |
printf("# device name %s\n", device); | |
printf("# sector size %lld bytes\n", sector_size); | |
printf("# # of sectors %lld\n", n_of_sectors); | |
printf("# volume %.3f GiB\n", (double) volume / (1 << 30)); | |
printf("#\n"); | |
printf("# block size %lu bytes\n", each_bytes); | |
printf("# total count %lld\n", count); | |
printf("# total size %.3f MB\n", total_size_mb); | |
printf("# elapsed time %f sec\n", elapsed_time_sec); | |
printf("# throughput %.3f MB/sec\n", throughput_mb_per_sec); | |
printf("# IOPS %.3f\n", count / elapsed_time_sec); | |
printf("# latency (mean) %f msec\n", elapsed_time_sec / count * 1e3); | |
printf("####################################\n"); | |
close(fd); | |
free(buffer); | |
free(tvs); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment