[PATCH] Add option for terse parseable output
authorJens Axboe <axboe@suse.de>
Mon, 12 Jun 2006 09:04:44 +0000 (11:04 +0200)
committerJens Axboe <axboe@suse.de>
Mon, 12 Jun 2006 09:04:44 +0000 (11:04 +0200)
README
fio.c
fio.h
init.c
stat.c

diff --git a/README b/README
index c951504eb52925c46678195d1783abd219ebf01f..d6ff1096ce4c8482adab333b626e8aac2f2fd07c 100644 (file)
--- a/README
+++ b/README
@@ -48,6 +48,7 @@ $ fio
        -w Generate per-job bandwidth logs
        -f <file> Read <file> for job descriptions
        -o <file> Log output to file
        -w Generate per-job bandwidth logs
        -f <file> Read <file> for job descriptions
        -o <file> Log output to file
+       -m Minimal (terse) output
        -h Print help info
        -v Print version information and exit
 
        -h Print help info
        -v Print version information and exit
 
@@ -303,6 +304,31 @@ util=              The disk utilization. A value of 100% means we kept the disk
                busy constantly, 50% would be a disk idling half of the time.
 
 
                busy constantly, 50% would be a disk idling half of the time.
 
 
+Terse output
+------------
+
+For scripted usage where you typically want to generate tables or graphs
+of the results, fio can output the results in a comma seperated format.
+The format is one long line of values, such as:
+
+client1,0,0,936,331,2894,0,0,0.000000,0.000000,1,170,22.115385,34.290410,16,714,84.252874%,366.500000,566.417819,3496,1237,2894,0,0,0.000000,0.000000,0,246,6.671625,21.436952,0,2534,55.465300%,1406.600000,2008.044216,0.000000%,0.431928%,1109
+
+Split up, the format is as follows:
+
+       jobname, groupid, error
+       READ status:
+               KiB IO, bandwidth (KiB/sec), runtime (msec)
+               Submission latency: min, max, mean, deviation
+               Completion latency: min, max, mean, deviation
+               Bw: min, max, aggreate percentage of total, mean, deviation
+       WRITE status:
+               KiB IO, bandwidth (KiB/sec), runtime (msec)
+               Submission latency: min, max, mean, deviation
+               Completion latency: min, max, mean, deviation
+               Bw: min, max, aggreate percentage of total, mean, deviation
+       CPU usage: user, system, context switches
+
+
 Author
 ------
 
 Author
 ------
 
diff --git a/fio.c b/fio.c
index b53a58ebe1883bbc9ad17f83fd598ce0c81c0c3c..445600f2074e6575a848f7eef622c2f181e8a89f 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -1576,7 +1576,7 @@ static void print_thread_status(void)
        char eta_str[32];
        double perc = 0.0;
 
        char eta_str[32];
        double perc = 0.0;
 
-       if (temp_stall_ts)
+       if (temp_stall_ts || terse_output)
                return;
 
        eta_secs = malloc(thread_number * sizeof(int));
                return;
 
        eta_secs = malloc(thread_number * sizeof(int));
@@ -1717,8 +1717,10 @@ static void run_threads(void)
 
        mlocked_mem = fio_pin_memory();
 
 
        mlocked_mem = fio_pin_memory();
 
-       printf("Starting %d thread%s\n", thread_number, thread_number > 1 ? "s" : "");
-       fflush(stdout);
+       if (!terse_output) {
+               printf("Starting %d thread%s\n", thread_number, thread_number > 1 ? "s" : "");
+               fflush(stdout);
+       }
 
        signal(SIGINT, sig_handler);
        signal(SIGALRM, sig_handler);
 
        signal(SIGINT, sig_handler);
        signal(SIGALRM, sig_handler);
diff --git a/fio.h b/fio.h
index cc68603499759b369f25b1038e30a07036074874..39d95874f22fe2277ddb56c1c643f2269d716374 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -324,6 +324,7 @@ extern int exitall_on_terminate;
 extern int thread_number;
 extern int shm_id;
 extern int groupid;
 extern int thread_number;
 extern int shm_id;
 extern int groupid;
+extern int terse_output;
 extern FILE *f_out;
 extern FILE *f_err;
 
 extern FILE *f_out;
 extern FILE *f_err;
 
diff --git a/init.c b/init.c
index bbc9aadff408e4049a3f7ef7cc592b725d1b3de5..40fcf1c35f61a5426648ee19dcfa9f680147bcf1 100644 (file)
--- a/init.c
+++ b/init.c
@@ -54,6 +54,7 @@ int rate_quit = 0;
 int write_lat_log = 0;
 int write_bw_log = 0;
 int exitall_on_terminate = 0;
 int write_lat_log = 0;
 int write_bw_log = 0;
 int exitall_on_terminate = 0;
+int terse_output = 0;
 unsigned long long mlock_size = 0;
 FILE *f_out = NULL;
 FILE *f_err = NULL;
 unsigned long long mlock_size = 0;
 FILE *f_out = NULL;
 FILE *f_err = NULL;
@@ -173,10 +174,12 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
 
        ddir = td->ddir + (!td->sequential << 1) + (td->iomix << 2);
 
 
        ddir = td->ddir + (!td->sequential << 1) + (td->iomix << 2);
 
-       if (!job_add_num)
-               fprintf(f_out, "%s: (g=%d): rw=%s, odir=%d, bs=%d-%d, rate=%d, ioengine=%s, iodepth=%d\n", td->name, td->groupid, ddir_str[ddir], td->odirect, td->min_bs, td->max_bs, td->rate, td->io_engine_name, td->iodepth);
-       else if (job_add_num == 1)
-               fprintf(f_out, "...\n");
+       if (!terse_output) {
+               if (!job_add_num)
+                       fprintf(f_out, "%s: (g=%d): rw=%s, odir=%d, bs=%d-%d, rate=%d, ioengine=%s, iodepth=%d\n", td->name, td->groupid, ddir_str[ddir], td->odirect, td->min_bs, td->max_bs, td->rate, td->io_engine_name, td->iodepth);
+               else if (job_add_num == 1)
+                       fprintf(f_out, "...\n");
+       }
 
        /*
         * recurse add identical jobs, clear numjobs and stonewall options
 
        /*
         * recurse add identical jobs, clear numjobs and stonewall options
@@ -965,6 +968,7 @@ static void usage(char *name)
        printf("\t-t Runtime in seconds\n");
        printf("\t-l Generate per-job latency logs\n");
        printf("\t-w Generate per-job bandwidth logs\n");
        printf("\t-t Runtime in seconds\n");
        printf("\t-l Generate per-job latency logs\n");
        printf("\t-w Generate per-job bandwidth logs\n");
+       printf("\t-m Minimal (terse) output\n");
        printf("\t-f Job file (Required)\n");
        printf("\t-v Print version info and exit\n");
 }
        printf("\t-f Job file (Required)\n");
        printf("\t-v Print version info and exit\n");
 }
@@ -973,7 +977,7 @@ static int parse_cmd_line(int argc, char *argv[])
 {
        int c, idx = 1, ini_idx = 0;
 
 {
        int c, idx = 1, ini_idx = 0;
 
-       while ((c = getopt(argc, argv, "t:o:f:lwvh")) != EOF) {
+       while ((c = getopt(argc, argv, "t:o:f:lwvhm")) != EOF) {
                switch (c) {
                        case 't':
                                def_timeout = atoi(optarg);
                switch (c) {
                        case 't':
                                def_timeout = atoi(optarg);
@@ -1002,6 +1006,10 @@ static int parse_cmd_line(int argc, char *argv[])
                                f_err = f_out;
                                idx++;
                                break;
                                f_err = f_out;
                                idx++;
                                break;
+                       case 'm':
+                               terse_output = 1;
+                               idx++;
+                               break;
                        case 'h':
                                usage(argv[0]);
                                exit(0);
                        case 'h':
                                usage(argv[0]);
                                exit(0);
diff --git a/stat.c b/stat.c
index f3aa2320c0a3c474f9495b9a258fb70ac376decf..4cc3b7e92fbe802d80cc10f5baee9d4babfb0dee 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -369,6 +369,63 @@ static void show_thread_status(struct thread_data *td,
        fprintf(f_out, "  cpu          : usr=%3.2f%%, sys=%3.2f%%, ctx=%lu\n", usr_cpu, sys_cpu, td->ctx);
 }
 
        fprintf(f_out, "  cpu          : usr=%3.2f%%, sys=%3.2f%%, ctx=%lu\n", usr_cpu, sys_cpu, td->ctx);
 }
 
+static void show_ddir_status_terse(struct thread_data *td,
+                                  struct group_run_stats *rs, int ddir)
+{
+       unsigned long min, max;
+       unsigned long long bw;
+       double mean, dev;
+
+       bw = 0;
+       if (td->runtime[ddir])
+               bw = td->io_bytes[ddir] / td->runtime[ddir];
+
+       fprintf(f_out, ",%llu,%llu,%lu", td->io_bytes[ddir] >> 10, bw, td->runtime[ddir]);
+
+       if (calc_lat(&td->slat_stat[ddir], &min, &max, &mean, &dev))
+               fprintf(f_out, ",%lu,%lu,%f,%f", min, max, mean, dev);
+       else
+               fprintf(f_out, ",%lu,%lu,%f,%f", 0UL, 0UL, 0.0, 0.0);
+
+       if (calc_lat(&td->clat_stat[ddir], &min, &max, &mean, &dev))
+               fprintf(f_out, ",%lu,%lu,%f,%f", min, max, mean, dev);
+       else
+               fprintf(f_out, ",%lu,%lu,%f,%f", 0UL, 0UL, 0.0, 0.0);
+
+       if (calc_lat(&td->bw_stat[ddir], &min, &max, &mean, &dev)) {
+               double p_of_agg;
+
+               p_of_agg = mean * 100 / (double) rs->agg[ddir];
+               fprintf(f_out, ",%lu,%lu,%f%%,%f,%f", min, max, p_of_agg, mean, dev);
+       } else
+               fprintf(f_out, ",%lu,%lu,%f%%,%f,%f", 0UL, 0UL, 0.0, 0.0, 0.0);
+               
+}
+
+
+static void show_thread_status_terse(struct thread_data *td,
+                                    struct group_run_stats *rs)
+{
+       double usr_cpu, sys_cpu;
+
+       fprintf(f_out, "%s,%d,%d",td->name, td->groupid, td->error);
+
+       show_ddir_status_terse(td, rs, 0);
+       show_ddir_status_terse(td, rs, 1);
+
+       if (td->runtime[0] + td->runtime[1]) {
+               double runt = td->runtime[0] + td->runtime[1];
+
+               usr_cpu = (double) td->usr_time * 100 / runt;
+               sys_cpu = (double) td->sys_time * 100 / runt;
+       } else {
+               usr_cpu = 0;
+               sys_cpu = 0;
+       }
+
+       fprintf(f_out, ",%f%%,%f%%,%lu\n", usr_cpu, sys_cpu, td->ctx);
+}
+
 void show_run_stats(void)
 {
        struct group_run_stats *runstats, *rs;
 void show_run_stats(void)
 {
        struct group_run_stats *runstats, *rs;
@@ -437,19 +494,25 @@ void show_run_stats(void)
        /*
         * don't overwrite last signal output
         */
        /*
         * don't overwrite last signal output
         */
-       printf("\n");
+       if (!terse_output)
+               printf("\n");
 
        for (i = 0; i < thread_number; i++) {
                td = &threads[i];
                rs = &runstats[td->groupid];
 
 
        for (i = 0; i < thread_number; i++) {
                td = &threads[i];
                rs = &runstats[td->groupid];
 
-               show_thread_status(td, rs);
+               if (terse_output)
+                       show_thread_status_terse(td, rs);
+               else
+                       show_thread_status(td, rs);
        }
 
        }
 
-       for (i = 0; i < groupid + 1; i++)
-               show_group_stats(&runstats[i], i);
+       if (!terse_output) {
+               for (i = 0; i < groupid + 1; i++)
+                       show_group_stats(&runstats[i], i);
 
 
-       show_disk_util();
+               show_disk_util();
+       }
 }
 
 static inline void add_stat_sample(struct io_stat *is, unsigned long val)
 }
 
 static inline void add_stat_sample(struct io_stat *is, unsigned long val)