Commit ae795c82 authored by Konstantin Khlebnikov's avatar Konstantin Khlebnikov

working set size, cleanups, fixes, etc...

parent 5501738a
...@@ -35,15 +35,29 @@ ...@@ -35,15 +35,29 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/mount.h>
#include <sys/ioctl.h>
long long now(void) void usage(void)
{ {
struct timeval tv; fprintf(stderr,
" Usage: ioping [-CDhq] [-c count] [-w deadline] [-p period]\n"
if (gettimeofday(&tv, NULL)) " [-i interval] [-s size] [-S wsize] [-o offset] device|file|directory\n"
err(1, "gettimeofday failed"); "\n"
" -c <count> stop after <count> requests\n"
return tv.tv_sec * 1000000ll + tv.tv_usec; " -w <deadline> stop after <deadline>\n"
" -p <period> print raw statistics for every <period> requests\n"
" -i <interval> interval between requests\n"
" -s <size> request size\n"
" -S <wsize> working set size\n"
" -o <offset> in file offset\n"
" -C use cached-io\n"
" -D use direct-io\n"
" -h display this mesage and exit\n"
" -q suppress human-readable output\n"
"\n"
);
exit(0);
} }
struct suffix { struct suffix {
...@@ -139,25 +153,14 @@ long long parse_time(const char *str) ...@@ -139,25 +153,14 @@ long long parse_time(const char *str)
return parse_suffix(str, sfx); return parse_suffix(str, sfx);
} }
void usage(void) long long now(void)
{ {
fprintf(stderr, struct timeval tv;
" Usage: ioping [-DCRhq] [-c count] [-w deadline] [-p pediod]\n"
" [-i interval] [-s size] [-o offset] device|file|directory\n" if (gettimeofday(&tv, NULL))
"\n" err(1, "gettimeofday failed");
" -c <count> stop after <count> requests\n"
" -w <deadline> stop after <deadline>\n" return tv.tv_sec * 1000000ll + tv.tv_usec;
" -p <period> print raw statistics every <period> requests\n"
" -i <interval> interval between requests\n"
" -s <size> request size\n"
" -o <offset> offset in file\n"
" -D use direct-io\n"
" -C use cached-io\n"
" -h display this mesage and exit\n"
" -q suppress human-readable output\n"
"\n"
);
exit(0);
} }
char *path = NULL; char *path = NULL;
...@@ -175,8 +178,11 @@ int cached = 0; ...@@ -175,8 +178,11 @@ int cached = 0;
long long interval = 1000000; long long interval = 1000000;
long long deadline = 0; long long deadline = 0;
ssize_t size = 512; ssize_t size = 1<<12;
ssize_t wsize = 1<<20;
off_t offset = 0; off_t offset = 0;
off_t woffset = 0;
int request; int request;
int count = 0; int count = 0;
...@@ -190,7 +196,7 @@ void parse_options(int argc, char **argv) ...@@ -190,7 +196,7 @@ void parse_options(int argc, char **argv)
if (argc < 2) if (argc < 2)
usage(); usage();
while ((opt = getopt(argc, argv, "-hDCqi:w:s:c:o:p:")) != -1) { while ((opt = getopt(argc, argv, "-hDCqi:w:s:S:c:o:p:")) != -1) {
switch (opt) { switch (opt) {
case 'h': case 'h':
usage(); usage();
...@@ -208,6 +214,13 @@ void parse_options(int argc, char **argv) ...@@ -208,6 +214,13 @@ void parse_options(int argc, char **argv)
break; break;
case 's': case 's':
size = parse_size(optarg); size = parse_size(optarg);
if (size > wsize)
wsize = size;
break;
case 'S':
wsize = parse_size(optarg);
if (wsize < size)
size = wsize;
break; break;
case 'o': case 'o':
offset = parse_size(optarg); offset = parse_size(optarg);
...@@ -301,28 +314,46 @@ int main (int argc, char **argv) ...@@ -301,28 +314,46 @@ int main (int argc, char **argv)
parse_options(argc, argv); parse_options(argc, argv);
flags = O_RDONLY;
if (direct)
flags |= O_DIRECT;
if (lstat(path, &stat)) if (lstat(path, &stat))
err(1, "stat \"%s\" failed", path); err(1, "stat \"%s\" failed", path);
if (S_ISREG(stat.st_mode) || S_ISDIR(stat.st_mode)) { if (S_ISDIR(stat.st_mode) || S_ISREG(stat.st_mode)) {
if (S_ISDIR(stat.st_mode))
stat.st_size = wsize;
if (!quiet) if (!quiet)
parse_device(stat.st_dev); parse_device(stat.st_dev);
} else if (S_ISBLK(stat.st_mode)) { } else if (S_ISBLK(stat.st_mode)) {
unsigned long long blksize;
fd = open(path, flags);
if (fd < 0)
err(1, "failed to open \"%s\"", path);
ret = ioctl(fd, BLKGETSIZE64, &blksize);
if (ret)
err(1, "block get size ioctl failed");
stat.st_size = blksize;
fstype = "block"; fstype = "block";
device = "device"; device = "device";
} else { } else {
errx(1, "unsupported destination: \"%s\"", path); errx(1, "unsupported destination: \"%s\"", path);
} }
if (wsize > stat.st_size)
wsize = stat.st_size;
if (size > stat.st_size)
size = stat.st_size;
buf = memalign(sysconf(_SC_PAGE_SIZE), size); buf = memalign(sysconf(_SC_PAGE_SIZE), size);
if (!buf) if (!buf)
errx(1, "buffer allocation failed"); errx(1, "buffer allocation failed");
memset(buf, '*', size); memset(buf, '*', size);
flags = O_RDONLY;
if (direct)
flags |= O_DIRECT;
if (S_ISDIR(stat.st_mode)) { if (S_ISDIR(stat.st_mode)) {
char *tmpl = "/ioping.XXXXXX"; char *tmpl = "/ioping.XXXXXX";
char *temp = malloc(strlen(path) + strlen(tmpl) + 1); char *temp = malloc(strlen(path) + strlen(tmpl) + 1);
...@@ -335,11 +366,13 @@ int main (int argc, char **argv) ...@@ -335,11 +366,13 @@ int main (int argc, char **argv)
err(1, "failed to create temporary file at \"%s\"", path); err(1, "failed to create temporary file at \"%s\"", path);
if (unlink(temp)) if (unlink(temp))
err(1, "unlink \"%s\" failed", temp); err(1, "unlink \"%s\" failed", temp);
if (pwrite(fd, buf, size, offset) != size) for (woffset = 0 ; woffset + size <= wsize ; woffset += size) {
if (pwrite(fd, buf, size, offset + woffset) != size)
err(1, "write failed"); err(1, "write failed");
}
if (fsync(fd)) if (fsync(fd))
err(1, "fsync failed"); err(1, "fsync failed");
} else { } else if (S_ISREG(stat.st_mode)) {
fd = open(path, flags); fd = open(path, flags);
if (fd < 0) if (fd < 0)
err(1, "failed to open \"%s\"", path); err(1, "failed to open \"%s\"", path);
...@@ -351,6 +384,8 @@ int main (int argc, char **argv) ...@@ -351,6 +384,8 @@ int main (int argc, char **argv)
set_signal(SIGINT, sig_exit); set_signal(SIGINT, sig_exit);
request = 0; request = 0;
woffset = 0;
part_min = time_min = LLONG_MAX; part_min = time_min = LLONG_MAX;
part_max = time_max = LLONG_MIN; part_max = time_max = LLONG_MIN;
part_sum = time_sum = 0; part_sum = time_sum = 0;
...@@ -367,14 +402,14 @@ int main (int argc, char **argv) ...@@ -367,14 +402,14 @@ int main (int argc, char **argv)
request++; request++;
if (!cached) { if (!cached) {
ret = posix_fadvise(fd, offset, size, ret = posix_fadvise(fd, offset + woffset, size,
POSIX_FADV_DONTNEED); POSIX_FADV_DONTNEED);
if (ret) if (ret)
err(1, "fadvise failed"); err(1, "fadvise failed");
} }
this_time = now(); this_time = now();
ret_size = pread(fd, buf, size, offset); ret_size = pread(fd, buf, size, offset + woffset);
if (ret_size < 0 && errno != EINTR) if (ret_size < 0 && errno != EINTR)
err(1, "read failed"); err(1, "read failed");
this_time = now() - this_time; this_time = now() - this_time;
...@@ -410,6 +445,10 @@ int main (int argc, char **argv) ...@@ -410,6 +445,10 @@ int main (int argc, char **argv)
part_sum = part_sum2 = 0; part_sum = part_sum2 = 0;
} }
woffset += size;
if (woffset + size > wsize)
woffset = 0;
if (!exiting) if (!exiting)
usleep(interval); usleep(interval);
} }
...@@ -430,7 +469,7 @@ int main (int argc, char **argv) ...@@ -430,7 +469,7 @@ int main (int argc, char **argv)
printf("\n--- %s ioping statistics ---\n", path); printf("\n--- %s ioping statistics ---\n", path);
printf("%d requests completed in %.1f ms\n", printf("%d requests completed in %.1f ms\n",
request, time_total/1000.); request, time_total/1000.);
printf(" min/avg/max/mdev = %.1f/%.1f/%.1f/%.1f ms\n", printf("min/avg/max/mdev = %.1f/%.1f/%.1f/%.1f ms\n",
time_min/1000., time_avg/1000., time_min/1000., time_avg/1000.,
time_max/1000., time_mdev/1000.); time_max/1000., time_mdev/1000.);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment