]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Improve the statistics reporting for xfs_io.
authorNathan Scott <nathans@sgi.com>
Wed, 9 Mar 2005 14:08:59 +0000 (14:08 +0000)
committerNathan Scott <nathans@sgi.com>
Wed, 9 Mar 2005 14:08:59 +0000 (14:08 +0000)
Merge of master-melb:xfs-cmds:21779a by kenmcd.

io/Makefile
io/getrusage.c [new file with mode: 0644]
io/init.c
io/init.h
io/input.c
io/input.h
io/io.h
io/pread.c
io/pwrite.c
io/sendfile.c

index 4b0838483dc0bf45b2598505b5bbb48af258983d..ff622e00352bf6f793289bed5ca52c95afc95763 100644 (file)
@@ -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 (file)
index 0000000..2b321fe
--- /dev/null
@@ -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 <xfs/libxfs.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#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);
+}
index dec5f53048602a12c8a22da4e8f118860da81a8e..2c3f6a5d262317b6061c627b80df360396531932 100644 (file)
--- 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 */
index c01975599779a7e9c5b65b592eec595c06d7babf..913718514af973a86366c64af4249ee91b5afa61 100644 (file)
--- 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;
index 9827692205606d1a445d01cb73d32e4aa3ede88b..11bf850af22da012f2cfa6c7b2a8ab47794f9433 100644 (file)
@@ -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);
+       }
 }
index ad79e0b31e468af9eb8d2dedd89625d2f4c30c12..36a19ee47fc8142abc3d46070951cd560e7c63eb 100644 (file)
@@ -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 cc5e76743b7caa5842a4e5f12d4c1ff3b24c96da..22633165b508f750208d57a1de5b96c3c4b6f2c7 100644 (file)
--- 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);
index 47ae5cf019c944dd0283b897e02fbaf323233460..52b38ce3a8616d03440cb1a8658a12e1ba156fdd 100644 (file)
@@ -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, &sectsize);
-       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;
 }
 
index 88c62222e3f80db2971ce3363e792b164ea2808c..f1d47c5fa8cad09744fa46f845839ec1ce988408 100644 (file)
@@ -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, &sectsize);
-       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;
 }
index f5d57b1a36769b2889d5bea1ea60e7928228a6d9..5607e8f088f97afaaee75a966c1bc144d1946c6f 100644 (file)
@@ -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, &sectsize);
-       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]");