Recent changes (master)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The following changes since commit 65f21d61d5d0796335ceb3320b8846e4d6d30ac7:

  xxhash: dos2unix'ize (2014-02-20 13:29:42 -0800)

are available in the git repository at:

  git://git.kernel.dk/fio.git master

for you to fetch changes up to 0de5b26f6e177aacac0683306c47e0cbaf58b0b6:

  Unify the time handling (2014-02-21 15:26:01 -0800)

----------------------------------------------------------------
Jens Axboe (3):
      Fixup time multipliers
      Improve latency_target runs
      Unify the time handling

 HOWTO     |    3 ++-
 backend.c |    6 +++---
 eta.c     |   20 ++++++++++++--------
 fio.1     |    4 ++--
 fio.h     |    2 ++
 init.c    |    4 ++--
 io_u.c    |   37 +++++++++++++++++++++++++++++++------
 libfio.c  |    2 +-
 options.c |    7 +++++--
 parse.c   |   40 ++++++++++++++++++++++++----------------
 parse.h   |    5 +++--
 stat.c    |   35 +++++++++++++++++++++++++++++++++++
 stat.h    |    1 +
 time.c    |    7 ++++++-
 time.h    |    1 +
 15 files changed, 130 insertions(+), 44 deletions(-)

---

Diff of recent changes:

diff --git a/HOWTO b/HOWTO
index bafad93..4dacd98 100644
--- a/HOWTO
+++ b/HOWTO
@@ -223,7 +223,8 @@ a string. The following types are used:
 str	String. This is a sequence of alpha characters.
 time	Integer with possible time suffix. In seconds unless otherwise
 	specified, use eg 10m for 10 minutes. Accepts s/m/h for seconds,
-	minutes, and hours.
+	minutes, and hours, and accepts 'ms' (or 'msec') for milliseconds,
+	and 'us' (or 'usec') for microseconds.
 int	SI integer. A whole number value, which may contain a suffix
 	describing the base of the number. Accepted suffixes are k/m/g/t/p,
 	meaning kilo, mega, giga, tera, and peta. The suffix is not case
diff --git a/backend.c b/backend.c
index 87aec87..ee395bd 100644
--- a/backend.c
+++ b/backend.c
@@ -346,7 +346,7 @@ static inline int runtime_exceeded(struct thread_data *td, struct timeval *t)
 		return 0;
 	if (!td->o.timeout)
 		return 0;
-	if (mtime_since(&td->epoch, t) >= td->o.timeout )
+	if (utime_since(&td->epoch, t) >= td->o.timeout)
 		return 1;
 
 	return 0;
@@ -1683,8 +1683,8 @@ static void do_usleep(unsigned int usecs)
 static void run_threads(void)
 {
 	struct thread_data *td;
-	unsigned long spent;
 	unsigned int i, todo, nr_running, m_rate, t_rate, nr_started;
+	uint64_t spent;
 
 	if (fio_gtod_offload && fio_start_gtod_thread())
 		return;
@@ -1782,7 +1782,7 @@ static void run_threads(void)
 			}
 
 			if (td->o.start_delay) {
-				spent = mtime_since_genesis();
+				spent = utime_since_genesis();
 
 				if (td->o.start_delay > spent)
 					continue;
diff --git a/eta.c b/eta.c
index e12e4fc..b050102 100644
--- a/eta.c
+++ b/eta.c
@@ -127,8 +127,10 @@ static int thread_eta(struct thread_data *td)
 	unsigned long long bytes_total, bytes_done;
 	unsigned long eta_sec = 0;
 	unsigned long elapsed;
+	uint64_t timeout;
 
 	elapsed = (mtime_since_now(&td->epoch) + 999) / 1000;
+	timeout = td->o.timeout / 1000000UL;
 
 	bytes_total = td->total_io_size;
 
@@ -174,8 +176,7 @@ static int thread_eta(struct thread_data *td)
 			perc = 1.0;
 
 		if (td->o.time_based) {
-			perc_t = (double) elapsed /
-					(double) (td->o.timeout / 1000);
+			perc_t = (double) elapsed / (double) timeout;
 			if (perc_t < perc)
 				perc = perc_t;
 		}
@@ -183,9 +184,8 @@ static int thread_eta(struct thread_data *td)
 		eta_sec = (unsigned long) (elapsed * (1.0 / perc)) - elapsed;
 
 		if (td->o.timeout &&
-		    eta_sec > ( (td->o.timeout / 1000) + done_secs - elapsed))
-			eta_sec = (td->o.timeout / 1000)  + done_secs
-			       		- elapsed;
+		    eta_sec > (timeout + done_secs - elapsed))
+			eta_sec = timeout + done_secs - elapsed;
 	} else if (td->runstate == TD_NOT_CREATED || td->runstate == TD_CREATED
 			|| td->runstate == TD_INITIALIZED
 			|| td->runstate == TD_SETTING_UP
@@ -199,8 +199,12 @@ static int thread_eta(struct thread_data *td)
 		 * if given, otherwise assume it'll run at the specified rate.
 		 */
 		if (td->o.timeout) {
-			t_eta = (td->o.timeout + td->o.start_delay  +
-					td->o.ramp_time ) / 1000;
+			uint64_t timeout = td->o.timeout;
+			uint64_t start_delay = td->o.start_delay;
+			uint64_t ramp_time = td->o.ramp_time;
+
+			t_eta = timeout + start_delay + ramp_time;
+			t_eta /= 1000000ULL;
 
 			if (in_ramp_time(td)) {
 				unsigned long ramp_left;
@@ -214,7 +218,7 @@ static int thread_eta(struct thread_data *td)
 		rate_bytes = ddir_rw_sum(td->o.rate);
 		if (rate_bytes) {
 			r_eta = (bytes_total / 1024) / rate_bytes;
-			r_eta += td->o.start_delay / 1000;
+			r_eta += (td->o.start_delay / 1000000ULL);
 		}
 
 		if (r_eta && t_eta)
diff --git a/fio.1 b/fio.1
index 81b03f7..c530d84 100644
--- a/fio.1
+++ b/fio.1
@@ -131,8 +131,8 @@ etc. This is useful for disk drives where values are often given in base 10
 values. Specifying '30GiB' will get you 30*1000^3 bytes.
 When specifying times the default suffix meaning changes, still denoting the
 base unit of the value, but accepted suffixes are 'D' (days), 'H' (hours), 'M'
-(minutes), 'S' Seconds, 'ms' milli seconds. Time values without a unit specify
-seconds.
+(minutes), 'S' Seconds, 'ms' (or msec) milli seconds, 'us' (or 'usec') micro
+seconds. Time values without a unit specify seconds.
 The suffixes are not case sensitive.
 .TP
 .I bool
diff --git a/fio.h b/fio.h
index d1180cd..9159b0c 100644
--- a/fio.h
+++ b/fio.h
@@ -262,6 +262,7 @@ struct thread_data {
 	unsigned int latency_qd_low;
 	unsigned int latency_failed;
 	uint64_t latency_ios;
+	int latency_end_run;
 
 	/*
 	 * read/write mixed workload state
@@ -504,6 +505,7 @@ extern int load_blktrace(struct thread_data *, const char *, int);
  */
 extern void lat_target_check(struct thread_data *);
 extern void lat_target_init(struct thread_data *);
+extern void lat_target_reset(struct thread_data *);
 
 #define for_each_td(td, i)	\
 	for ((i) = 0, (td) = &threads[0]; (i) < (int) thread_number; (i)++, (td)++)
diff --git a/init.c b/init.c
index 5fc3b22..6a65e55 100644
--- a/init.c
+++ b/init.c
@@ -1773,7 +1773,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 		case 'E': {
 			long long t = 0;
 
-			if (str_to_decimal(optarg, &t, 0, NULL)) {
+			if (str_to_decimal(optarg, &t, 0, NULL, 1)) {
 				log_err("fio: failed parsing eta time %s\n", optarg);
 				exit_val = 1;
 				do_exit++;
@@ -1933,7 +1933,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 		case 'L': {
 			long long val;
 
-			if (check_str_time(optarg, &val)) {
+			if (check_str_time(optarg, &val, 1)) {
 				log_err("fio: failed parsing time %s\n", optarg);
 				do_exit++;
 				exit_val = 1;
diff --git a/io_u.c b/io_u.c
index b84b3e2..619fa25 100644
--- a/io_u.c
+++ b/io_u.c
@@ -1162,6 +1162,10 @@ static int __lat_target_failed(struct thread_data *td)
 		return 1;
 
 	td->latency_qd_high = td->latency_qd;
+
+	if (td->latency_qd == td->latency_qd_low)
+		td->latency_qd_low--;
+
 	td->latency_qd = (td->latency_qd + td->latency_qd_low) / 2;
 
 	dprint(FD_RATE, "Ramped down: %d %d %d\n", td->latency_qd_low, td->latency_qd, td->latency_qd_high);
@@ -1186,6 +1190,8 @@ static int lat_target_failed(struct thread_data *td)
 
 void lat_target_init(struct thread_data *td)
 {
+	td->latency_end_run = 0;
+
 	if (td->o.latency_target) {
 		dprint(FD_RATE, "Latency target=%llu\n", td->o.latency_target);
 		fio_gettime(&td->latency_ts, NULL);
@@ -1197,9 +1203,16 @@ void lat_target_init(struct thread_data *td)
 		td->latency_qd = td->o.iodepth;
 }
 
+void lat_target_reset(struct thread_data *td)
+{
+	if (!td->latency_end_run)
+		lat_target_init(td);
+}
+
 static void lat_target_success(struct thread_data *td)
 {
 	const unsigned int qd = td->latency_qd;
+	struct thread_options *o = &td->o;
 
 	td->latency_qd_low = td->latency_qd;
 
@@ -1208,20 +1221,32 @@ static void lat_target_success(struct thread_data *td)
 	 * of bisecting from highest possible queue depth. If we have set
 	 * a limit other than td->o.iodepth, bisect between that.
 	 */
-	if (td->latency_qd_high != td->o.iodepth)
+	if (td->latency_qd_high != o->iodepth)
 		td->latency_qd = (td->latency_qd + td->latency_qd_high) / 2;
 	else
 		td->latency_qd *= 2;
 
-	if (td->latency_qd > td->o.iodepth)
-		td->latency_qd = td->o.iodepth;
+	if (td->latency_qd > o->iodepth)
+		td->latency_qd = o->iodepth;
 
 	dprint(FD_RATE, "Ramped up: %d %d %d\n", td->latency_qd_low, td->latency_qd, td->latency_qd_high);
+
 	/*
-	 * Same as last one, we are done
+	 * Same as last one, we are done. Let it run a latency cycle, so
+	 * we get only the results from the targeted depth.
 	 */
-	if (td->latency_qd == qd)
-		td->done = 1;
+	if (td->latency_qd == qd) {
+		if (td->latency_end_run) {
+			dprint(FD_RATE, "We are done\n");
+			td->done = 1;
+		} else {
+			dprint(FD_RATE, "Quiesce and final run\n");
+			io_u_quiesce(td);
+			td->latency_end_run = 1;
+			reset_all_stats(td);
+			reset_io_stats(td);
+		}
+	}
 
 	lat_new_cycle(td);
 }
diff --git a/libfio.c b/libfio.c
index 222cd16..f4aac2e 100644
--- a/libfio.c
+++ b/libfio.c
@@ -135,7 +135,7 @@ void reset_all_stats(struct thread_data *td)
 	memcpy(&td->epoch, &tv, sizeof(tv));
 	memcpy(&td->start, &tv, sizeof(tv));
 
-	lat_target_init(td);
+	lat_target_reset(td);
 }
 
 void reset_fio_state(void)
diff --git a/options.c b/options.c
index 87a4432..5355982 100644
--- a/options.c
+++ b/options.c
@@ -102,7 +102,7 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
 		} else
 			perc = -1;
 
-		if (str_to_decimal(fname, &val, 1, o)) {
+		if (str_to_decimal(fname, &val, 1, o, 0)) {
 			log_err("fio: bssplit conversion failed\n");
 			free(bssplit);
 			return 1;
@@ -336,7 +336,7 @@ static int str_rw_cb(void *data, const char *str)
 	else {
 		long long val;
 
-		if (str_to_decimal(nr, &val, 1, o)) {
+		if (str_to_decimal(nr, &val, 1, o, 0)) {
 			log_err("fio: rw postfix parsing failed\n");
 			free(nr);
 			return 1;
@@ -2068,6 +2068,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
 		.off2	= td_var_offset(start_delay_high),
 		.help	= "Only start job when this period has passed",
 		.def	= "0",
+		.is_seconds = 1,
 		.category = FIO_OPT_C_GENERAL,
 		.group	= FIO_OPT_G_RUNTIME,
 	},
@@ -2079,6 +2080,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
 		.off1	= td_var_offset(timeout),
 		.help	= "Stop workload when this amount of time has passed",
 		.def	= "0",
+		.is_seconds = 1,
 		.category = FIO_OPT_C_GENERAL,
 		.group	= FIO_OPT_G_RUNTIME,
 	},
@@ -2106,6 +2108,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
 		.type	= FIO_OPT_STR_VAL_TIME,
 		.off1	= td_var_offset(ramp_time),
 		.help	= "Ramp up time before measuring performance",
+		.is_seconds = 1,
 		.category = FIO_OPT_C_GENERAL,
 		.group	= FIO_OPT_G_RUNTIME,
 	},
diff --git a/parse.c b/parse.c
index c8bae03..079f19e 100644
--- a/parse.c
+++ b/parse.c
@@ -122,11 +122,12 @@ static void show_option_help(struct fio_option *o, int is_err)
 	show_option_values(o);
 }
 
-static unsigned long long get_mult_time(const char *str, int len)
+static unsigned long long get_mult_time(const char *str, int len,
+					int is_seconds)
 {
 	const char *p = str;
 	char *c;
-	unsigned long long mult = 1000;
+	unsigned long long mult = 1;
 
 	/*
          * Go forward until we hit a non-digit, or +/- sign
@@ -137,23 +138,29 @@ static unsigned long long get_mult_time(const char *str, int len)
 		p++;
 	}
 
-	if (!isalpha((int) *p))
-		return 1000;
+	if (!isalpha((int) *p)) {
+		if (is_seconds)
+			return 1000000UL;
+		else
+			return 1;
+	}
 
 	c = strdup(p);
 	for (int i = 0; i < strlen(c); i++)
 		c[i] = tolower(c[i]);
 
-	if (!strncmp("ms", c, 2))
+	if (!strncmp("us", c, 2) || !strncmp("usec", c, 4))
 		mult = 1;
-	else if (!strcmp("s", c))
+	else if (!strncmp("ms", c, 2) || !strncmp("msec", c, 4))
 		mult = 1000;
+	else if (!strcmp("s", c))
+		mult = 1000000;
 	else if (!strcmp("m", c))
-		mult = 60 * 1000;
+		mult = 60 * 1000000UL;
 	else if (!strcmp("h", c))
-		mult = 60 * 60 * 1000;
+		mult = 60 * 60 * 1000000UL;
 	else if (!strcmp("d", c))
-		mult = 24 * 60 * 60 * 1000;
+		mult = 24 * 60 * 60 * 1000000UL;
 
 	free(c);
 	return mult;
@@ -268,7 +275,8 @@ int str_to_float(const char *str, double *val)
 /*
  * convert string into decimal value, noting any size suffix
  */
-int str_to_decimal(const char *str, long long *val, int kilo, void *data)
+int str_to_decimal(const char *str, long long *val, int kilo, void *data,
+		   int is_seconds)
 {
 	int len, base;
 
@@ -295,19 +303,19 @@ int str_to_decimal(const char *str, long long *val, int kilo, void *data)
 		else
 			*val *= mult;
 	} else
-		*val *= get_mult_time(str, len);
+		*val *= get_mult_time(str, len, is_seconds);
 
 	return 0;
 }
 
 int check_str_bytes(const char *p, long long *val, void *data)
 {
-	return str_to_decimal(p, val, 1, data);
+	return str_to_decimal(p, val, 1, data, 0);
 }
 
-int check_str_time(const char *p, long long *val)
+int check_str_time(const char *p, long long *val, int is_seconds)
 {
-	return str_to_decimal(p, val, 0, NULL);
+	return str_to_decimal(p, val, 0, NULL, is_seconds);
 }
 
 void strip_blank_front(char **p)
@@ -349,7 +357,7 @@ static int check_range_bytes(const char *str, long *val, void *data)
 {
 	long long __val;
 
-	if (!str_to_decimal(str, &__val, 1, data)) {
+	if (!str_to_decimal(str, &__val, 1, data, 0)) {
 		*val = __val;
 		return 0;
 	}
@@ -459,7 +467,7 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data,
 			*p = '\0';
 
 		if (is_time)
-			ret = check_str_time(tmp, &ull);
+			ret = check_str_time(tmp, &ull, o->is_seconds);
 		else
 			ret = check_str_bytes(tmp, &ull, data);
 
diff --git a/parse.h b/parse.h
index 1009252..c797b92 100644
--- a/parse.h
+++ b/parse.h
@@ -72,6 +72,7 @@ struct fio_option {
 	unsigned int category;		/* what type of option */
 	unsigned int group;		/* who to group with */
 	void *gui_data;
+	int is_seconds;			/* time value with seconds base */
 };
 
 typedef int (str_cb_fn)(void *, char *);
@@ -87,9 +88,9 @@ extern void options_free(struct fio_option *, void *);
 
 extern void strip_blank_front(char **);
 extern void strip_blank_end(char *);
-extern int str_to_decimal(const char *, long long *, int, void *);
+extern int str_to_decimal(const char *, long long *, int, void *, int);
 extern int check_str_bytes(const char *p, long long *val, void *data);
-extern int check_str_time(const char *p, long long *val);
+extern int check_str_time(const char *p, long long *val, int);
 extern int str_to_float(const char *str, double *val);
 
 /*
diff --git a/stat.c b/stat.c
index bc01b51..e43db8f 100644
--- a/stat.c
+++ b/stat.c
@@ -1579,6 +1579,41 @@ static inline void reset_io_stat(struct io_stat *ios)
 	ios->mean.u.f = ios->S.u.f = 0;
 }
 
+void reset_io_stats(struct thread_data *td)
+{
+	struct thread_stat *ts = &td->ts;
+	int i, j;
+
+	for (i = 0; i < DDIR_RWDIR_CNT; i++) {
+		reset_io_stat(&ts->clat_stat[i]);
+		reset_io_stat(&ts->slat_stat[i]);
+		reset_io_stat(&ts->lat_stat[i]);
+		reset_io_stat(&ts->bw_stat[i]);
+		reset_io_stat(&ts->iops_stat[i]);
+
+		ts->io_bytes[i] = 0;
+		ts->runtime[i] = 0;
+
+		for (j = 0; j < FIO_IO_U_PLAT_NR; j++)
+			ts->io_u_plat[i][j] = 0;
+	}
+
+	for (i = 0; i < FIO_IO_U_MAP_NR; i++) {
+		ts->io_u_map[i] = 0;
+		ts->io_u_submit[i] = 0;
+		ts->io_u_complete[i] = 0;
+		ts->io_u_lat_u[i] = 0;
+		ts->io_u_lat_m[i] = 0;
+		ts->total_submit = 0;
+		ts->total_complete = 0;
+	}
+
+	for (i = 0; i < 3; i++) {
+		ts->total_io_u[i] = 0;
+		ts->short_io_u[i] = 0;
+	}
+}
+
 static void _add_stat_to_log(struct io_log *iolog, unsigned long elapsed)
 {
 	/*
diff --git a/stat.h b/stat.h
index 7ad0c9d..bc4f6da 100644
--- a/stat.h
+++ b/stat.h
@@ -224,6 +224,7 @@ extern unsigned int calc_clat_percentiles(unsigned int *io_u_plat, unsigned long
 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);
 extern void stat_calc_dist(unsigned int *map, unsigned long total, double *io_u_dist);
+extern void reset_io_stats(struct thread_data *);
 
 static inline int usec_to_msec(unsigned long *min, unsigned long *max,
 			       double *mean, double *dev)
diff --git a/time.c b/time.c
index b374d3e..f3de3e7 100644
--- a/time.c
+++ b/time.c
@@ -58,6 +58,11 @@ uint64_t mtime_since_genesis(void)
 	return mtime_since_now(&genesis);
 }
 
+uint64_t utime_since_genesis(void)
+{
+	return utime_since_now(&genesis);
+}
+
 int in_ramp_time(struct thread_data *td)
 {
 	return td->o.ramp_time && !td->ramp_time_over;
@@ -71,7 +76,7 @@ int ramp_time_over(struct thread_data *td)
 		return 1;
 
 	fio_gettime(&tv, NULL);
-	if (mtime_since(&td->epoch, &tv) >= td->o.ramp_time ) {
+	if (utime_since(&td->epoch, &tv) >= td->o.ramp_time) {
 		td->ramp_time_over = 1;
 		reset_all_stats(td);
 		td_set_runstate(td, TD_RAMP);
diff --git a/time.h b/time.h
index d835191..c550a55 100644
--- a/time.h
+++ b/time.h
@@ -7,6 +7,7 @@ extern uint64_t mtime_since(struct timeval *, struct timeval *);
 extern uint64_t mtime_since_now(struct timeval *);
 extern uint64_t time_since_now(struct timeval *);
 extern uint64_t mtime_since_genesis(void);
+extern uint64_t utime_since_genesis(void);
 extern void usec_spin(unsigned int);
 extern void usec_sleep(struct thread_data *, unsigned long);
 extern void fill_start_time(struct timeval *);
--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Linux SCSI]     [Linux IDE]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux