Skip to content

Commit

Permalink
nanosecond: update completion latency recording and normal, json outp…
Browse files Browse the repository at this point in the history
…ut to use nanoseconds

A new set of nsec bins (0-1, 2-3, 4-9, 10-19, ...) is created for tracking latencies.
The number of io_u_plat[] latency bins is increased by about 50% to accommodate the
greater resolution while retaining the same max latency value of ~9 seconds.

Example output

test: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=null, iodepth=1
fio-2.20-39-g83b3
Starting 1 process
Jobs: 1 (f=1): [R(1)][100.0%][r=14.6GiB/s,w=0KiB/s][r=3832k,w=0 IOPS][eta 00m:00s]
test: (groupid=0, jobs=1): err= 0: pid=17621: Thu Jun  1 15:09:38 2017
   read: IOPS=3784k, BW=14.4GiB/s (15.5GB/s)(144GiB/10000msec)
    clat (nsec): min=15, max=1685.2k, avg=26.92, stdev=433.62
     lat (nsec): min=46, max=5989.9k, avg=67.31, stdev=1659.58
    clat percentiles (nsec):
     |  1.00th=[   18],  5.00th=[   18], 10.00th=[   19], 20.00th=[   19],
     | 30.00th=[   22], 40.00th=[   22], 50.00th=[   25], 60.00th=[   26],
     | 70.00th=[   26], 80.00th=[   27], 90.00th=[   36], 95.00th=[   41],
     | 99.00th=[   46], 99.50th=[   50], 99.90th=[  104], 99.95th=[  139],
     | 99.99th=[ 7840]
   bw (  MiB/s): min=13393, max=15647, per=0.10%, avg=14784.86, stdev=558.40
    lat (nsec) : 20=20.87%, 50=78.57%, 100=0.43%, 250=0.10%, 500=0.01%
    lat (nsec) : 750=0.01%, 1000=0.01%
    lat (usec) : 2=0.01%, 4=0.01%, 10=0.01%, 20=0.01%, 50=0.01%
    lat (usec) : 100=0.01%, 250=0.01%, 500=0.01%, 1000=0.01%
    lat (msec) : 2=0.01%
  cpu          : usr=99.72%, sys=0.12%, ctx=321, majf=0, minf=8
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwt: total=37840231,0,0, short=0,0,0, dropped=0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
   READ: bw=14.4GiB/s (15.5GB/s), 14.4GiB/s-14.4GiB/s (15.5GB/s-15.5GB/s), io=144GiB (155GB), run=10000-10000msec
  • Loading branch information
vincentkfu committed Jun 21, 2017
1 parent 8b6a404 commit d6bb626
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 95 deletions.
2 changes: 2 additions & 0 deletions client.c
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,8 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src)
dst->io_u_complete[i] = le32_to_cpu(src->io_u_complete[i]);
}

for (i = 0; i < FIO_IO_U_LAT_N_NR; i++)
dst->io_u_lat_n[i] = le32_to_cpu(src->io_u_lat_n[i]);
for (i = 0; i < FIO_IO_U_LAT_U_NR; i++)
dst->io_u_lat_u[i] = le32_to_cpu(src->io_u_lat_u[i]);
for (i = 0; i < FIO_IO_U_LAT_M_NR; i++)
Expand Down
3 changes: 2 additions & 1 deletion fio_time.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
#include "lib/types.h"

struct thread_data;
extern uint64_t utime_since(const struct timespec *,const struct timespec *);
extern uint64_t ntime_since(const struct timespec *, const struct timespec *);
extern uint64_t utime_since(const struct timespec *, const struct timespec *);
extern uint64_t utime_since_now(const struct timespec *);
extern uint64_t mtime_since(const struct timespec *, const struct timespec *);
extern uint64_t mtime_since_now(const struct timespec *);
Expand Down
20 changes: 20 additions & 0 deletions gettime.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,26 @@ void fio_clock_init(void)
log_info("fio: clocksource=cpu may not be reliable\n");
}

uint64_t ntime_since(const struct timespec *s, const struct timespec *e)
{
int64_t sec, nsec;

sec = e->tv_sec - s->tv_sec;
nsec = e->tv_nsec - s->tv_nsec;
if (sec > 0 && nsec < 0) {
sec--;
nsec += 1000000000LL;
}

/*
* time warp bug on some kernels?
*/
if (sec < 0 || (sec == 0 && nsec < 0))
return 0;

return nsec + (sec * 1000000000LL);
}

uint64_t utime_since(const struct timespec *s, const struct timespec *e)
{
int64_t sec, usec;
Expand Down
87 changes: 66 additions & 21 deletions io_u.c
Original file line number Diff line number Diff line change
Expand Up @@ -989,11 +989,52 @@ void io_u_mark_depth(struct thread_data *td, unsigned int nr)
td->ts.io_u_map[idx] += nr;
}

static void io_u_mark_lat_usec(struct thread_data *td, unsigned long usec)
static void io_u_mark_lat_nsec(struct thread_data *td, unsigned long long nsec)
{
int idx = 0;

assert(usec < 1000);
assert(nsec < 1000);

switch (nsec) {
case 750 ... 999:
idx = 9;
break;
case 500 ... 749:
idx = 8;
break;
case 250 ... 499:
idx = 7;
break;
case 100 ... 249:
idx = 6;
break;
case 50 ... 99:
idx = 5;
break;
case 20 ... 49:
idx = 4;
break;
case 10 ... 19:
idx = 3;
break;
case 4 ... 9:
idx = 2;
break;
case 2 ... 3:
idx = 1;
case 0 ... 1:
break;
}

assert(idx < FIO_IO_U_LAT_N_NR);
td->ts.io_u_lat_n[idx]++;
}

static void io_u_mark_lat_usec(struct thread_data *td, unsigned long long usec)
{
int idx = 0;

assert(usec < 1000 && usec >= 1);

switch (usec) {
case 750 ... 999:
Expand Down Expand Up @@ -1030,10 +1071,12 @@ static void io_u_mark_lat_usec(struct thread_data *td, unsigned long usec)
td->ts.io_u_lat_u[idx]++;
}

static void io_u_mark_lat_msec(struct thread_data *td, unsigned long msec)
static void io_u_mark_lat_msec(struct thread_data *td, unsigned long long msec)
{
int idx = 0;

assert(msec >= 1);

switch (msec) {
default:
idx = 11;
Expand Down Expand Up @@ -1075,12 +1118,14 @@ static void io_u_mark_lat_msec(struct thread_data *td, unsigned long msec)
td->ts.io_u_lat_m[idx]++;
}

static void io_u_mark_latency(struct thread_data *td, unsigned long usec)
static void io_u_mark_latency(struct thread_data *td, unsigned long long nsec)
{
if (usec < 1000)
io_u_mark_lat_usec(td, usec);
if (nsec < 1000)
io_u_mark_lat_nsec(td, nsec);
else if (nsec < 1000000)
io_u_mark_lat_usec(td, nsec / 1000);
else
io_u_mark_lat_msec(td, usec / 1000);
io_u_mark_lat_msec(td, nsec / 1000000);
}

static unsigned int __get_next_fileno_rand(struct thread_data *td)
Expand Down Expand Up @@ -1729,7 +1774,7 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u,
const enum fio_ddir idx, unsigned int bytes)
{
const int no_reduce = !gtod_reduce(td);
unsigned long lusec = 0;
unsigned long long llnsec = 0;

if (td->parent)
td = td->parent;
Expand All @@ -1738,37 +1783,37 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u,
return;

if (no_reduce)
lusec = utime_since(&io_u->issue_time, &icd->time);
llnsec = ntime_since(&io_u->issue_time, &icd->time);

if (!td->o.disable_lat) {
unsigned long tusec;
unsigned long long tnsec;

tusec = utime_since(&io_u->start_time, &icd->time);
add_lat_sample(td, idx, tusec, bytes, io_u->offset);
tnsec = ntime_since(&io_u->start_time, &icd->time);
add_lat_sample(td, idx, tnsec, bytes, io_u->offset);

if (td->flags & TD_F_PROFILE_OPS) {
struct prof_io_ops *ops = &td->prof_io_ops;

if (ops->io_u_lat)
icd->error = ops->io_u_lat(td, tusec);
icd->error = ops->io_u_lat(td, tnsec/1000);
}

if (td->o.max_latency && tusec > td->o.max_latency)
lat_fatal(td, icd, tusec, td->o.max_latency);
if (td->o.latency_target && tusec > td->o.latency_target) {
if (td->o.max_latency && tnsec/1000 > td->o.max_latency)
lat_fatal(td, icd, tnsec/1000, td->o.max_latency);
if (td->o.latency_target && tnsec/1000 > td->o.latency_target) {
if (lat_target_failed(td))
lat_fatal(td, icd, tusec, td->o.latency_target);
lat_fatal(td, icd, tnsec/1000, td->o.latency_target);
}
}

if (ddir_rw(idx)) {
if (!td->o.disable_clat) {
add_clat_sample(td, idx, lusec, bytes, io_u->offset);
io_u_mark_latency(td, lusec);
add_clat_sample(td, idx, llnsec, bytes, io_u->offset);
io_u_mark_latency(td, llnsec);
}

if (!td->o.disable_bw && per_unit_log(td->bw_log))
add_bw_sample(td, io_u, bytes, lusec);
add_bw_sample(td, io_u, bytes, llnsec);

if (no_reduce && per_unit_log(td->iops_log))
add_iops_sample(td, io_u, bytes);
Expand Down Expand Up @@ -2000,7 +2045,7 @@ void io_u_queued(struct thread_data *td, struct io_u *io_u)
if (!td->o.disable_slat && ramp_time_over(td) && td->o.stats) {
unsigned long slat_time;

slat_time = utime_since(&io_u->start_time, &io_u->issue_time);
slat_time = ntime_since(&io_u->start_time, &io_u->issue_time);

if (td->parent)
td = td->parent;
Expand Down
2 changes: 2 additions & 0 deletions server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1497,6 +1497,8 @@ void fio_server_send_ts(struct thread_stat *ts, struct group_run_stats *rs)
p.ts.io_u_complete[i] = cpu_to_le32(ts->io_u_complete[i]);
}

for (i = 0; i < FIO_IO_U_LAT_N_NR; i++)
p.ts.io_u_lat_n[i] = cpu_to_le32(ts->io_u_lat_n[i]);
for (i = 0; i < FIO_IO_U_LAT_U_NR; i++)
p.ts.io_u_lat_u[i] = cpu_to_le32(ts->io_u_lat_u[i]);
for (i = 0; i < FIO_IO_U_LAT_M_NR; i++)
Expand Down

0 comments on commit d6bb626

Please sign in to comment.