Skip to content

Instantly share code, notes, and snippets.

@itiut
Created September 5, 2014 15:36
Show Gist options
  • Save itiut/779b3b68ee4441a2316a to your computer and use it in GitHub Desktop.
Save itiut/779b3b68ee4441a2316a to your computer and use it in GitHub Desktop.
a prototype of microbenchmark for sequential read
#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, &sector_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