Merge branch 'histogram-delta' of https://github.com/cronburg/fio into histogram
authorJens Axboe <axboe@fb.com>
Tue, 16 Aug 2016 20:47:09 +0000 (14:47 -0600)
committerJens Axboe <axboe@fb.com>
Tue, 16 Aug 2016 20:47:09 +0000 (14:47 -0600)
1  2 
iolog.c
iolog.h
stat.c
stat.h

diff --combined iolog.c
index b0c948bd53661d65561fe68277a7cdc298cc280b,ee1999a0da72124cbc0bb40e4125a9d54c3feb79..3cb12aba8d230a5e0826e87fa6aa7fe2512497c5
+++ b/iolog.c
@@@ -576,6 -576,9 +576,9 @@@ void setup_log(struct io_log **log, str
               const char *filename)
  {
        struct io_log *l;
+       int i;
+       struct io_u_plat_entry *entry;
+       struct flist_head *list;
  
        l = scalloc(1, sizeof(*l));
        INIT_FLIST_HEAD(&l->io_logs);
        l->filename = strdup(filename);
        l->td = p->td;
  
+       /* Initialize histogram lists for each r/w direction,
+        * with initial io_u_plat of all zeros:
+        */
+       for (i = 0; i < DDIR_RWDIR_CNT; i++) {
+               list = &l->hist_window[i].list.list;
+               INIT_FLIST_HEAD(list);
+               entry = calloc(1, sizeof(struct io_u_plat_entry));
+               flist_add(&entry->list, list);
+       }
        if (l->td && l->td->o.io_submit_mode != IO_MODE_OFFLOAD) {
                struct io_logs *p;
  
@@@ -661,24 -674,27 +674,27 @@@ void free_log(struct io_log *log
        sfree(log);
  }
  
- static inline unsigned long hist_sum(int j, int stride, unsigned int *io_u_plat)
+ static inline unsigned long hist_sum(int j, int stride, unsigned int *io_u_plat,
+               unsigned int *io_u_plat_last)
  {
        unsigned long sum;
        int k;
  
        for (k = sum = 0; k < stride; k++)
-               sum += io_u_plat[j + k];
+               sum += io_u_plat[j + k] - io_u_plat_last[j + k];
  
        return sum;
  }
  
 -void flush_hist_samples(FILE *f, int hist_coarseness, void *samples,
 -                      uint64_t sample_size)
 +static void flush_hist_samples(FILE *f, int hist_coarseness, void *samples,
 +                             uint64_t sample_size)
  {
        struct io_sample *s;
        int log_offset;
        uint64_t i, j, nr_samples;
+       struct io_u_plat_entry *entry, *entry_before;
        unsigned int *io_u_plat;
+       unsigned int *io_u_plat_before;
  
        int stride = 1 << hist_coarseness;
        
  
        for (i = 0; i < nr_samples; i++) {
                s = __get_sample(samples, log_offset, i);
-               io_u_plat = (unsigned int *) (uintptr_t) s->val;
+               
+               entry = (struct io_u_plat_entry *) s->val;
+               io_u_plat = entry->io_u_plat;
+               
+               entry_before = flist_first_entry(&entry->list, struct io_u_plat_entry, list);
+               io_u_plat_before = entry_before->io_u_plat;
+               
                fprintf(f, "%lu, %u, %u, ", (unsigned long)s->time,
                        io_sample_ddir(s), s->bs);
                for (j = 0; j < FIO_IO_U_PLAT_NR - stride; j += stride) {
-                       fprintf(f, "%lu, ", hist_sum(j, stride, io_u_plat));
+                       fprintf(f, "%lu, ", hist_sum(j, stride, io_u_plat, io_u_plat_before));
                }
                fprintf(f, "%lu\n", (unsigned long) 
-                       hist_sum(FIO_IO_U_PLAT_NR - stride, stride, io_u_plat));
-               free(io_u_plat);
+                       hist_sum(FIO_IO_U_PLAT_NR - stride, stride, io_u_plat,
+                                io_u_plat_before));
+               
+               flist_del(&entry_before->list);
+               free(entry_before);
        }
  }
  
diff --combined iolog.h
index 93e970e5f294e7185068bca259613d77f0108171,ade4f1b80b379fe163ab085c3795b0fe1e30416a..93a9536f2ffc31d089d4a0da78902b8be368e18e
+++ b/iolog.h
@@@ -18,9 -18,14 +18,14 @@@ struct io_stat 
        fio_fp64_t S;
  };
  
+ struct io_u_plat_list {
+       struct flist_head list;
+ };
  struct io_hist {
        uint64_t samples;
        unsigned long hist_last;
+       struct io_u_plat_list list;
  };
  
  /*
@@@ -109,11 -114,10 +114,11 @@@ struct io_log 
        unsigned long avg_msec;
        unsigned long avg_last;
  
 -  /*
 -   * Windowed latency histograms, for keeping track of when we need to
 -   * save a copy of the histogram every approximately hist_msec milliseconds.
 -   */
 +      /*
 +       * Windowed latency histograms, for keeping track of when we need to
 +       * save a copy of the histogram every approximately hist_msec
 +       * milliseconds.
 +       */
        struct io_hist hist_window[DDIR_RWDIR_CNT];
        unsigned long hist_msec;
        int hist_coarseness;
diff --combined stat.c
index 6f5f002b487aab90601ac5e5985ae886d8b728d1,b0ce54d98eee2938308a268418ab65e02bf5eca1..a3fa8363b34dbf0e68e3dce4d1f92ed6f94ead04
--- 1/stat.c
--- 2/stat.c
+++ b/stat.c
@@@ -257,13 -257,13 +257,13 @@@ out
                free(ovals);
  }
  
 -int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
 -           double *mean, double *dev)
 +bool calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
 +            double *mean, double *dev)
  {
        double n = (double) is->samples;
  
        if (n == 0)
 -              return 0;
 +              return false;
  
        *min = is->min_val;
        *max = is->max_val;
        else
                *dev = 0;
  
 -      return 1;
 +      return true;
  }
  
  void show_group_stats(struct group_run_stats *rs, struct buf_output *out)
@@@ -364,7 -364,7 +364,7 @@@ static void display_lat(const char *nam
        const char *base = "(usec)";
        char *minp, *maxp;
  
 -      if (!usec_to_msec(&min, &max, &mean, &dev))
 +      if (usec_to_msec(&min, &max, &mean, &dev))
                base = "(msec)";
  
        minp = num2str(min, 6, 1, 0, 0);
@@@ -1090,8 -1090,8 +1090,8 @@@ static void show_thread_status_terse_v3
        log_buf(out, "\n");
  }
  
 -void json_add_job_opts(struct json_object *root, const char *name,
 -                     struct flist_head *opt_list, bool num_jobs)
 +static void json_add_job_opts(struct json_object *root, const char *name,
 +                            struct flist_head *opt_list, bool num_jobs)
  {
        struct json_object *dir_object;
        struct flist_head *entry;
@@@ -2221,7 -2221,7 +2221,7 @@@ void add_clat_sample(struct thread_dat
                
                if (this_window >= iolog->hist_msec) {
                        unsigned int *io_u_plat;
-                       unsigned int *dst;
+                       struct io_u_plat_entry *dst;
  
                        /*
                         * Make a byte-for-byte copy of the latency histogram
                         * log file.
                         */
                        io_u_plat = (unsigned int *) td->ts.io_u_plat[ddir];
-                       dst = malloc(FIO_IO_U_PLAT_NR * sizeof(unsigned int));
-                       memcpy(dst, io_u_plat,
+                       dst = malloc(sizeof(struct io_u_plat_entry));
+                       memcpy(&(dst->io_u_plat), io_u_plat,
                                FIO_IO_U_PLAT_NR * sizeof(unsigned int));
-                       __add_log_sample(iolog, (unsigned long )dst, ddir, bs,
+                       flist_add(&dst->list, &hw->list.list);
+                       __add_log_sample(iolog, (unsigned long)dst, ddir, bs,
                                                elapsed, offset);
  
                        /*
diff --combined stat.h
index c3e343d2de2ff5f743b36d8b00cd101c0ee4ed04,f551edc1a5edaa408c6e932136f8eec66c52ecf2..e6f77599310db55e996d55cfc9ad7f5513f11963
--- 1/stat.h
--- 2/stat.h
+++ b/stat.h
@@@ -240,6 -240,11 +240,11 @@@ struct jobs_eta 
        uint8_t run_str[];
  } __attribute__((packed));
  
+ struct io_u_plat_entry {
+       struct flist_head list;
+       unsigned int io_u_plat[FIO_IO_U_PLAT_NR];
+ };
  extern struct fio_mutex *stat_mutex;
  
  extern struct jobs_eta *get_jobs_eta(bool force, size_t *size);
@@@ -249,7 -254,7 +254,7 @@@ extern void stat_exit(void)
  
  extern struct json_object * show_thread_status(struct thread_stat *ts, struct group_run_stats *rs, struct flist_head *, struct buf_output *);
  extern void show_group_stats(struct group_run_stats *rs, struct buf_output *);
 -extern int calc_thread_status(struct jobs_eta *je, int force);
 +extern bool calc_thread_status(struct jobs_eta *je, int force);
  extern void display_thread_status(struct jobs_eta *je);
  extern void show_run_stats(void);
  extern void __show_run_stats(void);
@@@ -261,7 -266,7 +266,7 @@@ extern void sum_group_stats(struct grou
  extern void init_thread_stat(struct thread_stat *ts);
  extern void init_group_run_stat(struct group_run_stats *gs);
  extern void eta_to_str(char *str, unsigned long eta_sec);
 -extern int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max, double *mean, double *dev);
 +extern bool calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max, double *mean, double *dev);
  extern unsigned int calc_clat_percentiles(unsigned int *io_u_plat, unsigned long nr, fio_fp64_t *plist, unsigned int **output, unsigned int *maxv, unsigned int *minv);
  extern void stat_calc_lat_m(struct thread_stat *ts, double *io_u_lat);
  extern void stat_calc_lat_u(struct thread_stat *ts, double *io_u_lat);
@@@ -286,18 -291,18 +291,18 @@@ extern int calc_log_samples(void)
  extern struct io_log *agg_io_log[DDIR_RWDIR_CNT];
  extern int write_bw_log;
  
 -static inline int usec_to_msec(unsigned long *min, unsigned long *max,
 -                             double *mean, double *dev)
 +static inline bool usec_to_msec(unsigned long *min, unsigned long *max,
 +                              double *mean, double *dev)
  {
        if (*min > 1000 && *max > 1000 && *mean > 1000.0 && *dev > 1000.0) {
                *min /= 1000;
                *max /= 1000;
                *mean /= 1000.0;
                *dev /= 1000.0;
 -              return 0;
 +              return true;
        }
  
 -      return 1;
 +      return false;
  }
  /*
   * Worst level condensing would be 1:5, so allow enough room for that