Add cache hit stats
authorJens Axboe <axboe@kernel.dk>
Fri, 14 Dec 2018 15:32:01 +0000 (08:32 -0700)
committerJens Axboe <axboe@kernel.dk>
Fri, 14 Dec 2018 15:32:46 +0000 (08:32 -0700)
With the aioring engine, we can get notified if a buffered read was
a cache hit or if it hit media. Add that to the output stats for
normal and json output.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
client.c
engines/aioring.c
server.c
server.h
stat.c
stat.h

index c8850440152889dadb397f4195c934e305a122c7..480425f683685664e19860e6e85ec3a50c7f96b3 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1039,6 +1039,9 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src)
                        dst->ss_bw_data[i] = le64_to_cpu(src->ss_bw_data[i]);
                }
        }
                        dst->ss_bw_data[i] = le64_to_cpu(src->ss_bw_data[i]);
                }
        }
+
+       dst->cachehit           = le64_to_cpu(src->cachehit);
+       dst->cachemiss          = le64_to_cpu(src->cachemiss);
 }
 
 static void convert_gs(struct group_run_stats *dst, struct group_run_stats *src)
 }
 
 static void convert_gs(struct group_run_stats *dst, struct group_run_stats *src)
index 46469dbfeacc28d7e58092269296e7142d1fb751..ce9a2aac6ce2b865b91ad0565453d55a4cca7504 100644 (file)
@@ -63,6 +63,8 @@ typedef uint16_t u16;
 
 #define IORING_SQ_NEED_WAKEUP  (1 << 0)
 
 
 #define IORING_SQ_NEED_WAKEUP  (1 << 0)
 
+#define IOEV_RES2_CACHEHIT     (1 << 0)
+
 struct aio_sq_ring {
        union {
                struct {
 struct aio_sq_ring {
        union {
                struct {
@@ -103,6 +105,9 @@ struct aioring_data {
 
        int queued;
        int cq_ring_off;
 
        int queued;
        int cq_ring_off;
+
+       uint64_t cachehit;
+       uint64_t cachemiss;
 };
 
 struct aioring_options {
 };
 
 struct aioring_options {
@@ -241,6 +246,13 @@ static struct io_u *fio_aioring_event(struct thread_data *td, int event)
        } else
                io_u->error = 0;
 
        } else
                io_u->error = 0;
 
+       if (io_u->ddir == DDIR_READ) {
+               if (ev->res2 & IOEV_RES2_CACHEHIT)
+                       ld->cachehit++;
+               else
+                       ld->cachemiss++;
+       }
+
        return io_u;
 }
 
        return io_u;
 }
 
@@ -431,6 +443,9 @@ static void fio_aioring_cleanup(struct thread_data *td)
        struct aioring_data *ld = td->io_ops_data;
 
        if (ld) {
        struct aioring_data *ld = td->io_ops_data;
 
        if (ld) {
+               td->ts.cachehit += ld->cachehit;
+               td->ts.cachemiss += ld->cachemiss;
+
                /* Bump depth to match init depth */
                td->o.iodepth++;
 
                /* Bump depth to match init depth */
                td->o.iodepth++;
 
index 96e51819d38b8d89dca0a9e444a70cc1da5aa076..2a33770733e99e447f16511061f9f21a2699f2f5 100644 (file)
--- a/server.c
+++ b/server.c
@@ -1563,6 +1563,9 @@ void fio_server_send_ts(struct thread_stat *ts, struct group_run_stats *rs)
        p.ts.ss_deviation.u.i   = cpu_to_le64(fio_double_to_uint64(ts->ss_deviation.u.f));
        p.ts.ss_criterion.u.i   = cpu_to_le64(fio_double_to_uint64(ts->ss_criterion.u.f));
 
        p.ts.ss_deviation.u.i   = cpu_to_le64(fio_double_to_uint64(ts->ss_deviation.u.f));
        p.ts.ss_criterion.u.i   = cpu_to_le64(fio_double_to_uint64(ts->ss_criterion.u.f));
 
+       p.ts.cachehit           = cpu_to_le64(ts->cachehit);
+       p.ts.cachemiss          = cpu_to_le64(ts->cachemiss);
+
        convert_gs(&p.rs, rs);
 
        dprint(FD_NET, "ts->ss_state = %d\n", ts->ss_state);
        convert_gs(&p.rs, rs);
 
        dprint(FD_NET, "ts->ss_state = %d\n", ts->ss_state);
index 371e51ea24e85206ac857a1f62bf623b8b044e9f..abb23bad490d155d6e7935d7cd165e331376f6e7 100644 (file)
--- a/server.h
+++ b/server.h
@@ -48,7 +48,7 @@ struct fio_net_cmd_reply {
 };
 
 enum {
 };
 
 enum {
-       FIO_SERVER_VER                  = 77,
+       FIO_SERVER_VER                  = 78,
 
        FIO_SERVER_MAX_FRAGMENT_PDU     = 1024,
        FIO_SERVER_MAX_CMD_MB           = 2048,
 
        FIO_SERVER_MAX_FRAGMENT_PDU     = 1024,
        FIO_SERVER_MAX_CMD_MB           = 2048,
diff --git a/stat.c b/stat.c
index 887509fe0a104a0f6b0ae804d33fcfc4026c82b3..ec75de241be623756c88c1b88edb69473a0dfb97 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -419,7 +419,7 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts,
        unsigned long runt;
        unsigned long long min, max, bw, iops;
        double mean, dev;
        unsigned long runt;
        unsigned long long min, max, bw, iops;
        double mean, dev;
-       char *io_p, *bw_p, *bw_p_alt, *iops_p, *zbd_w_st = NULL;
+       char *io_p, *bw_p, *bw_p_alt, *iops_p, *post_st = NULL;
        int i2p;
 
        if (ddir_sync(ddir)) {
        int i2p;
 
        if (ddir_sync(ddir)) {
@@ -451,15 +451,25 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts,
        iops = (1000 * (uint64_t)ts->total_io_u[ddir]) / runt;
        iops_p = num2str(iops, ts->sig_figs, 1, 0, N2S_NONE);
        if (ddir == DDIR_WRITE)
        iops = (1000 * (uint64_t)ts->total_io_u[ddir]) / runt;
        iops_p = num2str(iops, ts->sig_figs, 1, 0, N2S_NONE);
        if (ddir == DDIR_WRITE)
-               zbd_w_st = zbd_write_status(ts);
+               post_st = zbd_write_status(ts);
+       else if (ddir == DDIR_READ && ts->cachehit && ts->cachemiss) {
+               uint64_t total;
+               double hit;
+
+               total = ts->cachehit + ts->cachemiss;
+               hit = (double) ts->cachehit / (double) total;
+               hit *= 100.0;
+               if (asprintf(&post_st, "; Cachehit=%0.2f%%", hit) < 0)
+                       post_st = NULL;
+       }
 
        log_buf(out, "  %s: IOPS=%s, BW=%s (%s)(%s/%llumsec)%s\n",
                        rs->unified_rw_rep ? "mixed" : io_ddir_name(ddir),
                        iops_p, bw_p, bw_p_alt, io_p,
                        (unsigned long long) ts->runtime[ddir],
 
        log_buf(out, "  %s: IOPS=%s, BW=%s (%s)(%s/%llumsec)%s\n",
                        rs->unified_rw_rep ? "mixed" : io_ddir_name(ddir),
                        iops_p, bw_p, bw_p_alt, io_p,
                        (unsigned long long) ts->runtime[ddir],
-                       zbd_w_st ? : "");
+                       post_st ? : "");
 
 
-       free(zbd_w_st);
+       free(post_st);
        free(io_p);
        free(bw_p);
        free(bw_p_alt);
        free(io_p);
        free(bw_p);
        free(bw_p_alt);
@@ -1153,6 +1163,16 @@ static void add_ddir_status_json(struct thread_stat *ts,
        json_object_add_value_float(dir_object, "iops_stddev", dev);
        json_object_add_value_int(dir_object, "iops_samples",
                                (&ts->iops_stat[ddir])->samples);
        json_object_add_value_float(dir_object, "iops_stddev", dev);
        json_object_add_value_int(dir_object, "iops_samples",
                                (&ts->iops_stat[ddir])->samples);
+
+       if (ts->cachehit + ts->cachemiss) {
+               uint64_t total;
+               double hit;
+
+               total = ts->cachehit + ts->cachemiss;
+               hit = (double) ts->cachehit / (double) total;
+               hit *= 100.0;
+               json_object_add_value_float(dir_object, "cachehit", hit);
+       }
 }
 
 static void show_thread_status_terse_all(struct thread_stat *ts,
 }
 
 static void show_thread_status_terse_all(struct thread_stat *ts,
@@ -1695,6 +1715,8 @@ void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src,
        dst->total_submit += src->total_submit;
        dst->total_complete += src->total_complete;
        dst->nr_zone_resets += src->nr_zone_resets;
        dst->total_submit += src->total_submit;
        dst->total_complete += src->total_complete;
        dst->nr_zone_resets += src->nr_zone_resets;
+       dst->cachehit += src->cachehit;
+       dst->cachemiss += src->cachemiss;
 }
 
 void init_group_run_stat(struct group_run_stats *gs)
 }
 
 void init_group_run_stat(struct group_run_stats *gs)
@@ -2376,6 +2398,7 @@ void reset_io_stats(struct thread_data *td)
        ts->total_submit = 0;
        ts->total_complete = 0;
        ts->nr_zone_resets = 0;
        ts->total_submit = 0;
        ts->total_complete = 0;
        ts->nr_zone_resets = 0;
+       ts->cachehit = ts->cachemiss = 0;
 }
 
 static void __add_stat_to_log(struct io_log *iolog, enum fio_ddir ddir,
 }
 
 static void __add_stat_to_log(struct io_log *iolog, enum fio_ddir ddir,
diff --git a/stat.h b/stat.h
index b4ba71e3b0df3b9131e46132622e5cc4c88de78b..e9551381ce7b7fd10092c195033ff2b911f2aa75 100644 (file)
--- a/stat.h
+++ b/stat.h
@@ -246,6 +246,9 @@ struct thread_stat {
                uint64_t *ss_bw_data;
                uint64_t pad5;
        };
                uint64_t *ss_bw_data;
                uint64_t pad5;
        };
+
+       uint64_t cachehit;
+       uint64_t cachemiss;
 } __attribute__((packed));
 
 struct jobs_eta {
 } __attribute__((packed));
 
 struct jobs_eta {