From 5c7bef679b2b11d8fc23fad3bd93c05420e2b8cc Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Wed, 9 Mar 2005 14:08:59 +0000 Subject: [PATCH] Improve the statistics reporting for xfs_io. Merge of master-melb:xfs-cmds:21779a by kenmcd. --- io/Makefile | 7 ++- io/getrusage.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++ io/init.c | 8 ++- io/init.h | 3 +- io/input.c | 28 +++++++--- io/input.h | 9 +++- io/io.h | 3 +- io/pread.c | 29 +++++++---- io/pwrite.c | 32 ++++++++---- io/sendfile.c | 29 +++++++---- 10 files changed, 240 insertions(+), 44 deletions(-) create mode 100644 io/getrusage.c diff --git a/io/Makefile b/io/Makefile index 4b0838483..ff622e003 100644 --- a/io/Makefile +++ b/io/Makefile @@ -36,10 +36,9 @@ include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_io LSRCFILES = xfs_bmap.sh xfs_freeze.sh HFILES = command.h input.h init.h io.h -CFILES = command.c input.c init.c \ - attr.c bmap.c file.c freeze.c fsync.c help.c \ - mmap.c open.c pread.c prealloc.c pwrite.c quit.c \ - truncate.c +CFILES = command.c input.c init.c help.c quit.c \ + attr.c bmap.c file.c freeze.c fsync.c getrusage.c \ + mmap.c open.c pread.c prealloc.c pwrite.c truncate.c ifeq ($(HAVE_FADVISE),yes) CFILES += fadvise.c diff --git a/io/getrusage.c b/io/getrusage.c new file mode 100644 index 000000000..2b321fe7b --- /dev/null +++ b/io/getrusage.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#include +#include +#include +#include "command.h" +#include "input.h" +#include "init.h" + +static cmdinfo_t getrusage_cmd; + +/* + * Report process resource utilisation. Formatting options: + * "Shell" format: 0.000u 0.000s 0:00.00 0.0% 0+0k 0+0io 0pf+0w + * Verbose format: + * 0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k + * 0inputs+0outputs (0major+0minor)pagefaults 0swaps + * Comma Separated Value format: 0.000,0.000,00:00:00.00,0.0,0,0,0,0,0,0 + */ +static int +getrusage_f( + int argc, + char **argv) +{ + struct timeval wallclk, timenow; + struct rusage rusage; + double usrtime, systime, elapsed, pct_cpu; + char ts[64]; + int Cflag, vflag; + int c; + + Cflag = vflag = 0; + while ((c = getopt(argc, argv, "Cv")) != EOF) { + switch (c) { + case 'C': + Cflag = 1; + break; + case 'v': + vflag = 1; + break; + default: + return command_usage(&getrusage_cmd); + } + } + if (optind != argc) + return command_usage(&getrusage_cmd); + + if (getrusage(RUSAGE_SELF, &rusage) < 0) { + perror("getrusage"); + return 0; + } + + gettimeofday(&timenow, NULL); + wallclk = tsub(timenow, stopwatch); + elapsed = (double)wallclk.tv_sec + + ((double)wallclk.tv_usec / 1000000.0); + usrtime = (double)rusage.ru_utime.tv_sec + + ((double)rusage.ru_utime.tv_usec / 1000000.0); + systime = (double)rusage.ru_stime.tv_sec + + ((double)rusage.ru_stime.tv_usec / 1000000.0); + if (elapsed < usrtime + systime) + pct_cpu = 100.0; + else + pct_cpu = ((usrtime + systime) / elapsed) * 100; + c = Cflag ? VERBOSE_FIXED_TIME : TERSE_FIXED_TIME; + timestr(&wallclk, ts, sizeof(ts), c); + + if (Cflag) + printf("%.3f,%.3f,%s,%.1f,%ld,%ld,%ld,%ld,%ld,%ld,%ld\n", + usrtime, systime, ts, pct_cpu, + rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap, + rusage.ru_inblock, rusage.ru_oublock, + rusage.ru_nvcsw, rusage.ru_nivcsw); + else if (vflag) + printf("%.2fuser %.2fsystem %selapsed %.0f%%CPU " + "(%ldavgtext+%ldavgdata %ldmaxresident)k\n" + "%ldinputs+%ldoutputs " + "(%ldmajor+%ldminor)pagefaults %ldswaps\n", + usrtime, systime, ts, pct_cpu, + rusage.ru_ixrss, rusage.ru_idrss, rusage.ru_maxrss, + rusage.ru_inblock, rusage.ru_oublock, + rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap); + else + printf("%.3fu %.3fs %s %.1f%%\t" + "%ld+%ldk %ld+%ldio %ldpf+%ldw\n", + usrtime, systime, ts, pct_cpu, + rusage.ru_maxrss, rusage.ru_ixrss, + rusage.ru_inblock, rusage.ru_oublock, + rusage.ru_majflt, rusage.ru_nswap); + return 0; +} + +void +getrusage_init(void) +{ + getrusage_cmd.name = _("getrusage"); + getrusage_cmd.altname = _("g"); + getrusage_cmd.argmin = 0; + getrusage_cmd.argmax = -1; + getrusage_cmd.cfunc = getrusage_f; + getrusage_cmd.flags = CMD_NOFILE_OK | CMD_NOMAP_OK | CMD_FOREIGN_OK; + getrusage_cmd.oneline = _("report process resource usage"); + + if (expert) + add_command(&getrusage_cmd); +} diff --git a/io/init.c b/io/init.c index dec5f5304..2c3f6a5d2 100644 --- a/io/init.c +++ b/io/init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -39,6 +39,7 @@ char *progname; int exitcode; int expert; size_t pagesize; +struct timeval stopwatch; static int ncmdline; static char **cmdline; @@ -61,6 +62,7 @@ init_commands(void) file_init(); freeze_init(); fsync_init(); + getrusage_init(); help_init(); inject_init(); mmap_init(); @@ -86,11 +88,13 @@ init( xfs_fsop_geom_t geometry = { 0 }; progname = basename(argv[0]); - pagesize = getpagesize(); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + pagesize = getpagesize(); + gettimeofday(&stopwatch, NULL); + while ((c = getopt(argc, argv, "ac:dFfmp:rRstVx")) != EOF) { switch (c) { case 'a': /* append */ diff --git a/io/init.h b/io/init.h index c01975599..913718514 100644 --- a/io/init.h +++ b/io/init.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -34,3 +34,4 @@ extern char *progname; extern int exitcode; extern int expert; extern size_t pagesize; +extern struct timeval stopwatch; diff --git a/io/input.c b/io/input.c index 982769220..11bf850af 100644 --- a/io/input.c +++ b/io/input.c @@ -266,15 +266,29 @@ void timestr( struct timeval *tv, char *ts, - size_t size) + size_t size, + int format) { - if (!tv->tv_sec) - snprintf(ts, size, "%.4f sec", - ((double) tv->tv_usec / 1000000.0)); - else - snprintf(ts, size, "%02u:%02u:%02u.%-u", + double usec = (double)tv->tv_usec / 1000000.0; + + if (format & TERSE_FIXED_TIME) { + if (!HOURS(tv->tv_sec)) { + snprintf(ts, size, "%u:%02u.%02u", + (unsigned int) MINUTES(tv->tv_sec), + (unsigned int) SECONDS(tv->tv_sec), + (unsigned int) usec * 100); + return; + } + format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */ + } + + if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) { + snprintf(ts, size, "%u:%02u:%02u.%02u", (unsigned int) HOURS(tv->tv_sec), (unsigned int) MINUTES(tv->tv_sec), (unsigned int) SECONDS(tv->tv_sec), - (unsigned int) tv->tv_usec); + (unsigned int) usec * 100); + } else { + snprintf(ts, size, "0.%04u sec", (unsigned int) usec * 10000); + } } diff --git a/io/input.h b/io/input.h index ad79e0b31..36a19ee47 100644 --- a/io/input.h +++ b/io/input.h @@ -38,5 +38,12 @@ extern long long cvtnum(int blocksize, int sectorsize, char *s); extern void cvtstr(double value, char *str, size_t sz); extern struct timeval tsub(struct timeval t1, struct timeval t2); extern double tdiv(double value, struct timeval tv); -extern void timestr(struct timeval *tv, char *str, size_t sz); + +enum { + DEFAULT_TIME = 0x0, + TERSE_FIXED_TIME = 0x1, + VERBOSE_FIXED_TIME = 0x2, +}; + +extern void timestr(struct timeval *tv, char *str, size_t sz, int flags); diff --git a/io/io.h b/io/io.h index cc5e76743..22633165b 100644 --- a/io/io.h +++ b/io/io.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -92,6 +92,7 @@ extern void bmap_init(void); extern void file_init(void); extern void freeze_init(void); extern void fsync_init(void); +extern void getrusage_init(void); extern void help_init(void); extern void inject_init(void); extern void mmap_init(void); diff --git a/io/pread.c b/io/pread.c index 47ae5cf01..52b38ce3a 100644 --- a/io/pread.c +++ b/io/pread.c @@ -152,11 +152,12 @@ pread_f( int blocksize, sectsize; struct timeval t1, t2; char s1[64], s2[64], ts[64]; - int uflag = 0, vflag = 0; + int Cflag, uflag, vflag; int c; + Cflag = uflag = vflag = 0; init_cvtnum(&blocksize, §size); - while ((c = getopt(argc, argv, "b:uv")) != EOF) { + while ((c = getopt(argc, argv, "b:Cuv")) != EOF) { switch (c) { case 'b': blocksize = cvtnum(blocksize, sectsize, optarg); @@ -165,6 +166,9 @@ pread_f( return 0; } break; + case 'C': + Cflag = 1; + break; case 'u': uflag = 1; break; @@ -199,13 +203,20 @@ pread_f( gettimeofday(&t2, NULL); t2 = tsub(t2, t1); - printf(_("read %lld/%lld bytes at offset %lld\n"), - total, count, (long long)offset); - cvtstr((double)total, s1, sizeof(s1)); - cvtstr(tdiv((double)total, t2), s2, sizeof(s2)); - timestr(&t2, ts, sizeof(ts)); - printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"), - s1, c, ts, s2, tdiv((double)c, t2)); + /* Finally, report back -- -C gives a parsable format */ + timestr(&t2, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0); + if (!Cflag) { + cvtstr((double)total, s1, sizeof(s1)); + cvtstr(tdiv((double)total, t2), s2, sizeof(s2)); + printf(_("read %lld/%lld bytes at offset %lld\n"), + total, count, (long long)offset); + printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"), + s1, c, ts, s2, tdiv((double)c, t2)); + } else {/* bytes,ops,time,bytes/sec,ops/sec */ + printf("%lld,%d,%s,%.3f,%.3f\n", + total, c, ts, + tdiv((double)total, t2), tdiv((double)c, t2)); + } return 0; } diff --git a/io/pwrite.c b/io/pwrite.c index 88c62222e..f1d47c5fa 100644 --- a/io/pwrite.c +++ b/io/pwrite.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -110,10 +110,12 @@ pwrite_f( struct timeval t1, t2; char s1[64], s2[64], ts[64]; char *sp, *infile = NULL; - int c, fd = -1, uflag = 0, dflag = 0, wflag = 0, Wflag = 0; + int Cflag, uflag, dflag, wflag, Wflag; + int c, fd = -1; + Cflag = uflag = dflag = wflag = Wflag = 0; init_cvtnum(&blocksize, §size); - while ((c = getopt(argc, argv, "b:df:i:s:S:uwW")) != EOF) { + while ((c = getopt(argc, argv, "b:Cdf:i:s:S:uwW")) != EOF) { switch (c) { case 'b': blocksize = cvtnum(blocksize, sectsize, optarg); @@ -122,6 +124,9 @@ pwrite_f( return 0; } break; + case 'C': + Cflag = 1; + break; case 'd': dflag = 1; break; @@ -190,13 +195,20 @@ pwrite_f( gettimeofday(&t2, NULL); t2 = tsub(t2, t1); - printf(_("wrote %lld/%lld bytes at offset %lld\n"), - total, count, (long long)offset); - cvtstr((double)total, s1, sizeof(s1)); - cvtstr(tdiv((double)total, t2), s2, sizeof(s2)); - timestr(&t2, ts, sizeof(ts)); - printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"), - s1, c, ts, s2, tdiv((double)c, t2)); + /* Finally, report back -- -C gives a parsable format */ + timestr(&t2, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0); + if (!Cflag) { + cvtstr((double)total, s1, sizeof(s1)); + cvtstr(tdiv((double)total, t2), s2, sizeof(s2)); + printf(_("wrote %lld/%lld bytes at offset %lld\n"), + total, count, (long long)offset); + printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"), + s1, c, ts, s2, tdiv((double)c, t2)); + } else {/* bytes,ops,time,bytes/sec,ops/sec */ + printf("%lld,%d,%s,%.3f,%.3f\n", + total, c, ts, + tdiv((double)total, t2), tdiv((double)c, t2)); + } close(fd); return 0; } diff --git a/io/sendfile.c b/io/sendfile.c index f5d57b1a3..5607e8f08 100644 --- a/io/sendfile.c +++ b/io/sendfile.c @@ -98,11 +98,15 @@ sendfile_f( struct timeval t1, t2; char s1[64], s2[64], ts[64]; char *infile = NULL; + int Cflag; int c, fd = -1; + Cflag = 0; init_cvtnum(&blocksize, §size); - while ((c = getopt(argc, argv, "f:i:")) != EOF) { + while ((c = getopt(argc, argv, "Cf:i:")) != EOF) { switch (c) { + case 'C': + Cflag = 1; case 'f': fd = atoi(argv[1]); if (fd < 0 || fd >= filecount) { @@ -157,13 +161,20 @@ sendfile_f( gettimeofday(&t2, NULL); t2 = tsub(t2, t1); - printf(_("sent %lld/%lld bytes from offset %lld\n"), - total, count, (long long)offset); - cvtstr((double)total, s1, sizeof(s1)); - cvtstr(tdiv((double)total, t2), s2, sizeof(s2)); - timestr(&t2, ts, sizeof(ts)); - printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"), - s1, c, ts, s2, tdiv((double)c, t2)); + /* Finally, report back -- -C gives a parsable format */ + timestr(&t2, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0); + if (!Cflag) { + cvtstr((double)total, s1, sizeof(s1)); + cvtstr(tdiv((double)total, t2), s2, sizeof(s2)); + printf(_("sent %lld/%lld bytes from offset %lld\n"), + total, count, (long long)offset); + printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"), + s1, c, ts, s2, tdiv((double)c, t2)); + } else {/* bytes,ops,time,bytes/sec,ops/sec */ + printf("%lld,%d,%s,%.3f,%.3f\n", + total, c, ts, + tdiv((double)total, t2), tdiv((double)c, t2)); + } done: if (infile) close(fd); @@ -177,7 +188,7 @@ sendfile_init(void) sendfile_cmd.altname = _("send"); sendfile_cmd.cfunc = sendfile_f; sendfile_cmd.argmin = 2; - sendfile_cmd.argmax = 4; + sendfile_cmd.argmax = -1; sendfile_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; sendfile_cmd.args = _("-i infile | -f N [off len]"); -- 2.47.2