write_type_log for each log type, instead of the default zero-based
timestamps.
+.. option:: log_alternate_epoch=bool
+
+ If set, fio will log timestamps based on the epoch used by the clock specified
+ in the log_alternate_epoch_clock_id option, to the log files produced by
+ enabling write_type_log for each log type, instead of the default zero-based
+ timestamps.
+
+.. option:: log_alternate_epoch_clock_id=int
+
+ Specifies the clock_id to be used by clock_gettime to obtain the alternate epoch
+ if either log_unix_epoch or log_alternate_epoch are true. Otherwise has no
+ effect. Default value is 0, or CLOCK_REALTIME.
+
.. option:: block_error_percentiles=bool
If set, record errors in trim block-sized units from writes and trims and
if (rate_submit_init(td, sk_out))
goto err;
- set_epoch_time(td, o->log_unix_epoch);
+ set_epoch_time(td, o->log_unix_epoch | o->log_alternate_epoch, o->log_alternate_epoch_clock_id);
fio_getrusage(&td->ru_start);
memcpy(&td->bw_sample_time, &td->epoch, sizeof(td->epoch));
memcpy(&td->iops_sample_time, &td->epoch, sizeof(td->epoch));
o->log_gz = le32_to_cpu(top->log_gz);
o->log_gz_store = le32_to_cpu(top->log_gz_store);
o->log_unix_epoch = le32_to_cpu(top->log_unix_epoch);
+ o->log_alternate_epoch = le32_to_cpu(top->log_alternate_epoch);
+ o->log_alternate_epoch_clock_id = le32_to_cpu(top->log_alternate_epoch_clock_id);
o->norandommap = le32_to_cpu(top->norandommap);
o->softrandommap = le32_to_cpu(top->softrandommap);
o->bs_unaligned = le32_to_cpu(top->bs_unaligned);
top->log_gz = cpu_to_le32(o->log_gz);
top->log_gz_store = cpu_to_le32(o->log_gz_store);
top->log_unix_epoch = cpu_to_le32(o->log_unix_epoch);
+ top->log_alternate_epoch = cpu_to_le32(o->log_alternate_epoch);
+ top->log_alternate_epoch_clock_id = cpu_to_le32(o->log_alternate_epoch_clock_id);
top->norandommap = cpu_to_le32(o->norandommap);
top->softrandommap = cpu_to_le32(o->softrandommap);
top->bs_unaligned = cpu_to_le32(o->bs_unaligned);
write_type_log for each log type, instead of the default zero-based
timestamps.
.TP
+.BI log_alternate_epoch \fR=\fPbool
+If set, fio will log timestamps based on the epoch used by the clock specified
+in the \fBlog_alternate_epoch_clock_id\fR option, to the log files produced by
+enabling write_type_log for each log type, instead of the default zero-based
+timestamps.
+.TP
+.BI log_alternate_epoch_clock_id \fR=\fPint
+Specifies the clock_id to be used by clock_gettime to obtain the alternate epoch
+if either \fBBlog_unix_epoch\fR or \fBlog_alternate_epoch\fR are true. Otherwise has no
+effect. Default value is 0, or CLOCK_REALTIME.
+.TP
.BI block_error_percentiles \fR=\fPbool
If set, record errors in trim block-sized units from writes and trims and
output a histogram of how many trims it took to get to errors, and what kind
struct timespec start; /* start of this loop */
struct timespec epoch; /* time job was started */
- unsigned long long unix_epoch; /* Time job was started, unix epoch based. */
+ unsigned long long alternate_epoch; /* Time job was started, clock_gettime's clock_id epoch based. */
struct timespec last_issue;
long time_offset;
struct timespec ts_cache;
extern bool in_ramp_time(struct thread_data *);
extern void fio_time_init(void);
extern void timespec_add_msec(struct timespec *, unsigned int);
-extern void set_epoch_time(struct thread_data *, int);
+extern void set_epoch_time(struct thread_data *, int, int);
#endif
td->ts.runtime[i] = 0;
}
- set_epoch_time(td, td->o.log_unix_epoch);
+ set_epoch_time(td, td->o.log_unix_epoch | td->o.log_alternate_epoch, td->o.log_alternate_epoch_clock_id);
memcpy(&td->start, &td->epoch, sizeof(td->epoch));
memcpy(&td->iops_sample_time, &td->epoch, sizeof(td->epoch));
memcpy(&td->bw_sample_time, &td->epoch, sizeof(td->epoch));
.category = FIO_OPT_C_LOG,
.group = FIO_OPT_G_INVALID,
},
+ {
+ .name = "log_alternate_epoch",
+ .lname = "Log epoch alternate",
+ .type = FIO_OPT_BOOL,
+ .off1 = offsetof(struct thread_options, log_alternate_epoch),
+ .help = "Use alternate epoch time in log files. Uses the same epoch as that is used by clock_gettime with specified log_alternate_epoch_clock_id.",
+ .category = FIO_OPT_C_LOG,
+ .group = FIO_OPT_G_INVALID,
+ },
+ {
+ .name = "log_alternate_epoch_clock_id",
+ .lname = "Log alternate epoch clock_id",
+ .type = FIO_OPT_INT,
+ .off1 = offsetof(struct thread_options, log_alternate_epoch_clock_id),
+ .help = "If log_alternate_epoch or log_unix_epoch is true, this option specifies the clock_id from clock_gettime whose epoch should be used. If neither of those is true, this option has no effect. Default value is 0, or CLOCK_REALTIME",
+ .category = FIO_OPT_C_LOG,
+ .group = FIO_OPT_G_INVALID,
+ },
{
.name = "block_error_percentiles",
.lname = "Block error percentiles",
return 0;
}
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW 4
+#endif
+
/*
* Get the value of a local clock source.
- * This implementation supports 2 clocks: CLOCK_MONOTONIC provides high-accuracy
- * relative time, while CLOCK_REALTIME provides a low-accuracy wall time.
+ * This implementation supports 3 clocks: CLOCK_MONOTONIC/CLOCK_MONOTONIC_RAW
+ * provide high-accuracy relative time, while CLOCK_REALTIME provides a
+ * low-accuracy wall time.
*/
int clock_gettime(clockid_t clock_id, struct timespec *tp)
{
int rc = 0;
- if (clock_id == CLOCK_MONOTONIC) {
+ if (clock_id == CLOCK_MONOTONIC || clock_id == CLOCK_MONOTONIC_RAW) {
static LARGE_INTEGER freq = {{0,0}};
LARGE_INTEGER counts;
uint64_t t;
if (td->io_ops->post_init && td->io_ops->post_init(td))
goto err_io_init;
- set_epoch_time(td, td->o.log_unix_epoch);
+ set_epoch_time(td, td->o.log_unix_epoch | td->o.log_alternate_epoch, td->o.log_alternate_epoch_clock_id);
fio_getrusage(&td->ru_start);
clear_io_state(td, 1);
s = get_sample(iolog, cur_log, cur_log->nr_samples);
s->data = data;
- s->time = t + (iolog->td ? iolog->td->unix_epoch : 0);
+ s->time = t + (iolog->td ? iolog->td->alternate_epoch : 0);
io_sample_set_ddir(iolog, s, ddir);
s->bs = bs;
s->priority = priority;
unsigned int log_gz;
unsigned int log_gz_store;
unsigned int log_unix_epoch;
+ unsigned int log_alternate_epoch;
+ unsigned int log_alternate_epoch_clock_id;
unsigned int norandommap;
unsigned int softrandommap;
unsigned int bs_unaligned;
uint32_t log_gz;
uint32_t log_gz_store;
uint32_t log_unix_epoch;
+ uint32_t log_alternate_epoch;
+ uint32_t log_alternate_epoch_clock_id;
uint32_t norandommap;
uint32_t softrandommap;
uint32_t bs_unaligned;
fio_gettime(&genesis, NULL);
}
-void set_epoch_time(struct thread_data *td, int log_unix_epoch)
+void set_epoch_time(struct thread_data *td, int log_alternate_epoch, clockid_t clock_id)
{
fio_gettime(&td->epoch, NULL);
- if (log_unix_epoch) {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- td->unix_epoch = (unsigned long long)(tv.tv_sec) * 1000 +
- (unsigned long long)(tv.tv_usec) / 1000;
+ if (log_alternate_epoch) {
+ struct timespec ts;
+ clock_gettime(clock_id, &ts);
+ td->alternate_epoch = (unsigned long long)(ts.tv_sec) * 1000 +
+ (unsigned long long)(ts.tv_nsec) / 1000000;
}
}