From 96563db9995c5cebdce526f2bf97923153d4456b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 14 Dec 2018 08:32:01 -0700 Subject: [PATCH] Add cache hit stats 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 --- client.c | 3 +++ engines/aioring.c | 15 +++++++++++++++ server.c | 3 +++ server.h | 2 +- stat.c | 31 +++++++++++++++++++++++++++---- stat.h | 3 +++ 6 files changed, 52 insertions(+), 5 deletions(-) diff --git a/client.c b/client.c index c8850440..480425f6 100644 --- 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->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) diff --git a/engines/aioring.c b/engines/aioring.c index 46469dbf..ce9a2aac 100644 --- a/engines/aioring.c +++ b/engines/aioring.c @@ -63,6 +63,8 @@ typedef uint16_t u16; #define IORING_SQ_NEED_WAKEUP (1 << 0) +#define IOEV_RES2_CACHEHIT (1 << 0) + struct aio_sq_ring { union { struct { @@ -103,6 +105,9 @@ struct aioring_data { int queued; int cq_ring_off; + + uint64_t cachehit; + uint64_t cachemiss; }; 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; + if (io_u->ddir == DDIR_READ) { + if (ev->res2 & IOEV_RES2_CACHEHIT) + ld->cachehit++; + else + ld->cachemiss++; + } + 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) { + td->ts.cachehit += ld->cachehit; + td->ts.cachemiss += ld->cachemiss; + /* Bump depth to match init depth */ td->o.iodepth++; diff --git a/server.c b/server.c index 96e51819..2a337707 100644 --- 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.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); diff --git a/server.h b/server.h index 371e51ea..abb23bad 100644 --- a/server.h +++ b/server.h @@ -48,7 +48,7 @@ struct fio_net_cmd_reply { }; enum { - FIO_SERVER_VER = 77, + FIO_SERVER_VER = 78, FIO_SERVER_MAX_FRAGMENT_PDU = 1024, FIO_SERVER_MAX_CMD_MB = 2048, diff --git a/stat.c b/stat.c index 887509fe..ec75de24 100644 --- 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; - 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)) { @@ -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) - 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], - zbd_w_st ? : ""); + post_st ? : ""); - free(zbd_w_st); + free(post_st); 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); + + 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, @@ -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->cachehit += src->cachehit; + dst->cachemiss += src->cachemiss; } 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->cachehit = ts->cachemiss = 0; } static void __add_stat_to_log(struct io_log *iolog, enum fio_ddir ddir, diff --git a/stat.h b/stat.h index b4ba71e3..e9551381 100644 --- a/stat.h +++ b/stat.h @@ -246,6 +246,9 @@ struct thread_stat { uint64_t *ss_bw_data; uint64_t pad5; }; + + uint64_t cachehit; + uint64_t cachemiss; } __attribute__((packed)); struct jobs_eta { -- 2.25.1