Recent changes

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

 



The following changes since commit 03f0a3c55c495bf9ef0668d2b6b047eb499e5e3f:

  Fio 1.38 (2010-03-23 08:29:38 +0100)

are available in the git repository at:
  git://git.kernel.dk/fio.git master

Jens Axboe (4):
      Add support for specific clock sources
      Merge branch 'master' of ssh://router/data/git/fio
      Add IA64 support for CPU clock
      Remove default setting of clocksource

 README             |    2 +
 arch/arch-ia64.h   |   10 +++++
 arch/arch-x86.h    |   10 +++++
 arch/arch-x86_64.h |   10 +++++
 debug.h            |    1 +
 fio.h              |   22 +---------
 gettime.c          |  106 +++++++++++++++++++++++++++++++++++++++++++++++++---
 init.c             |    1 +
 options.c          |   32 ++++++++++++++++
 time.c             |    6 ++-
 time.h             |   32 ++++++++++++++++
 11 files changed, 206 insertions(+), 26 deletions(-)
 create mode 100644 time.h

---

Diff of recent changes:

diff --git a/README b/README
index d5235de..e64853e 100644
--- a/README
+++ b/README
@@ -127,6 +127,8 @@ options in fio. Currently the options are:
 	diskutil	Dump info related to disk utilization updates
 	job:x		Dump info only related to job number x
 	mutex		Dump info only related to mutex up/down ops
+	profile		Dump info related to profile extensions
+	time		Dump info related to internal time keeping
 	? or help	Show available debug options.
 
 You can specify as many as you want, eg --debug=file,mem will enable
diff --git a/arch/arch-ia64.h b/arch/arch-ia64.h
index a8bb23a..056f636 100644
--- a/arch/arch-ia64.h
+++ b/arch/arch-ia64.h
@@ -33,6 +33,16 @@ static inline unsigned long arch_ffz(unsigned long bitmask)
 {
 	return ia64_popcnt(bitmask & (~bitmask - 1));
 }
+
+static inline unsigned long get_cpu_clock(void)
+{
+	unsigned long ret;
+
+	__asm__ __volatile__("mov %0=ar.itc" : "=r" (ret) : : "memory");
+	return ret;
+}
+
 #define ARCH_HAVE_FFZ
+#define ARCH_HAVE_CPU_CLOCK
 
 #endif
diff --git a/arch/arch-x86.h b/arch/arch-x86.h
index 9631437..bffd1dd 100644
--- a/arch/arch-x86.h
+++ b/arch/arch-x86.h
@@ -38,7 +38,17 @@ static inline unsigned long arch_ffz(unsigned long bitmask)
 	__asm__("bsfl %1,%0" :"=r" (bitmask) :"r" (~bitmask));
 	return bitmask;
 }
+
+static inline unsigned long long get_cpu_clock(void)
+{
+	unsigned long ret;
+
+	__asm__ __volatile__("rdtsc" : "=A" (ret));
+	return ret;
+}
+
 #define ARCH_HAVE_FFZ
 #define ARCH_HAVE_SSE
+#define ARCH_HAVE_CPU_CLOCK
 
 #endif
diff --git a/arch/arch-x86_64.h b/arch/arch-x86_64.h
index 457714c..3ea8070 100644
--- a/arch/arch-x86_64.h
+++ b/arch/arch-x86_64.h
@@ -38,7 +38,17 @@ static inline unsigned int arch_ffz(unsigned int bitmask)
 	__asm__("bsfl %1,%0" :"=r" (bitmask) :"r" (~bitmask));
 	return bitmask;
 }
+
+static inline unsigned long long get_cpu_clock(void)
+{
+	unsigned int lo, hi;
+
+	__asm__ __volatile__("rdtsc" : "=a" (lo), "=d" (hi));
+	return ((unsigned long long) hi << 32ULL) | lo;
+}
+
 #define ARCH_HAVE_FFZ
 #define ARCH_HAVE_SSE
+#define ARCH_HAVE_CPU_CLOCK
 
 #endif
diff --git a/debug.h b/debug.h
index e51d8b2..3473d6f 100644
--- a/debug.h
+++ b/debug.h
@@ -17,6 +17,7 @@ enum {
 	FD_JOB,
 	FD_MUTEX,
 	FD_PROFILE,
+	FD_TIME,
 	FD_DEBUG_MAX,
 };
 
diff --git a/fio.h b/fio.h
index 05911c0..5038e4d 100644
--- a/fio.h
+++ b/fio.h
@@ -31,6 +31,7 @@
 #include "helpers.h"
 #include "options.h"
 #include "profile.h"
+#include "time.h"
 
 #ifdef FIO_HAVE_GUASI
 #include <guasi.h>
@@ -238,6 +239,7 @@ struct thread_options {
 	unsigned int gtod_reduce;
 	unsigned int gtod_cpu;
 	unsigned int gtod_offload;
+	enum fio_cs clocksource;
 
 	char *read_iolog_file;
 	char *write_iolog_file;
@@ -481,6 +483,7 @@ extern unsigned long done_secs;
 extern char *job_section;
 extern int fio_gtod_offload;
 extern int fio_gtod_cpu;
+extern enum fio_cs fio_clock_source;
 
 extern struct thread_data *threads;
 
@@ -518,25 +521,6 @@ static inline int should_fsync(struct thread_data *td)
 }
 
 /*
- * Time functions
- */
-extern unsigned long long utime_since(struct timeval *, struct timeval *);
-extern unsigned long long utime_since_now(struct timeval *);
-extern unsigned long mtime_since(struct timeval *, struct timeval *);
-extern unsigned long mtime_since_now(struct timeval *);
-extern unsigned long time_since_now(struct timeval *);
-extern unsigned long mtime_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 *);
-extern void fio_gettime(struct timeval *, void *);
-extern void fio_gtod_init(void);
-extern void fio_gtod_update(void);
-extern void set_genesis_time(void);
-extern int ramp_time_over(struct thread_data *);
-extern int in_ramp_time(struct thread_data *);
-
-/*
  * Init/option functions
  */
 extern int __must_check parse_options(int, char **);
diff --git a/gettime.c b/gettime.c
index 8ec70b9..08d2d2b 100644
--- a/gettime.c
+++ b/gettime.c
@@ -3,6 +3,7 @@
  */
 
 #include <unistd.h>
+#include <math.h>
 #include <sys/time.h>
 
 #include "fio.h"
@@ -10,14 +11,17 @@
 
 #include "hash.h"
 
-static int clock_gettime_works = 0;
+static unsigned long cycles_per_usec;
 static struct timeval last_tv;
+static unsigned long last_cycles;
 static int last_tv_valid;
 
 static struct timeval *fio_tv;
 int fio_gtod_offload = 0;
 int fio_gtod_cpu = -1;
 
+enum fio_cs fio_clock_source = CS_GTOD;
+
 #ifdef FIO_DEBUG_TIME
 
 #define HASH_BITS	8
@@ -124,19 +128,44 @@ void fio_gettime(struct timeval *tp, void fio_unused *caller)
 	if (fio_tv) {
 		memcpy(tp, fio_tv, sizeof(*tp));
 		return;
-	} else if (!clock_gettime_works) {
-gtod:
+	}
+
+	switch (fio_clock_source) {
+	case CS_GTOD:
 		gettimeofday(tp, NULL);
-	} else {
+		break;
+	case CS_CGETTIME: {
 		struct timespec ts;
 
 		if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
-			clock_gettime_works = 0;
-			goto gtod;
+			log_err("fio: clock_gettime fails\n");
+			assert(0);
 		}
 
 		tp->tv_sec = ts.tv_sec;
 		tp->tv_usec = ts.tv_nsec / 1000;
+		break;
+		}
+#ifdef ARCH_HAVE_CPU_CLOCK
+	case CS_CPUCLOCK: {
+		unsigned long long usecs, t;
+
+		t = get_cpu_clock();
+		if (t < last_cycles) {
+			dprint(FD_TIME, "CPU clock going back in time\n");
+			t = last_cycles;
+		}
+
+		usecs = t / cycles_per_usec;
+		tp->tv_sec = usecs / 1000000;
+		tp->tv_usec = usecs % 1000000;
+		last_cycles = t;
+		break;
+		}
+#endif
+	default:
+		log_err("fio: invalid clock source %d\n", fio_clock_source);
+		break;
 	}
 
 	/*
@@ -154,6 +183,71 @@ gtod:
 	memcpy(&last_tv, tp, sizeof(*tp));
 }
 
+static unsigned long get_cycles_per_usec(void)
+{
+	struct timeval s, e;
+	unsigned long long c_s, c_e;
+
+	gettimeofday(&s, NULL);
+	c_s = get_cpu_clock();
+	do {
+		unsigned long long elapsed;
+
+		gettimeofday(&e, NULL);
+		elapsed = utime_since(&s, &e);
+		if (elapsed >= 10) {
+			c_e = get_cpu_clock();
+			break;
+		}
+	} while (1);
+
+	return c_e - c_s;
+}
+
+void fio_clock_init(void)
+{
+	double delta, mean, S;
+	unsigned long avg, cycles[10];
+	int i, samples;
+
+	last_tv_valid = 0;
+
+	cycles[0] = get_cycles_per_usec();
+	S = delta = mean = 0.0;
+	for (i = 0; i < 10; i++) {
+		cycles[i] = get_cycles_per_usec();
+		delta = cycles[i] - mean;
+		if (delta) {
+			mean += delta / (i + 1.0);
+			S += delta * (cycles[i] - mean);
+		}
+	}
+
+	S = sqrt(S / (10 - 1.0));
+
+	samples = avg = 0;
+	for (i = 0; i < 10; i++) {
+		double this = cycles[i];
+
+		if ((max(this, mean) - min(this, mean)) > S)
+			continue;
+		samples++;
+		avg += this;
+	}
+
+	S /= 10.0;
+	mean /= 10.0;
+
+	for (i = 0; i < 10; i++)
+		dprint(FD_TIME, "cycles[%d]=%lu\n", i, cycles[i] / 10);
+
+	avg /= (samples * 10);
+	dprint(FD_TIME, "avg: %lu\n", avg);
+	dprint(FD_TIME, "mean=%f, S=%f\n", mean, S);
+
+	cycles_per_usec = avg;
+}
+
 void fio_gtod_init(void)
 {
 	fio_tv = smalloc(sizeof(struct timeval));
diff --git a/init.c b/init.c
index 59c5f7c..4d0a906 100644
--- a/init.c
+++ b/init.c
@@ -992,6 +992,7 @@ struct debug_level debug_levels[] = {
 	{ .name = "job",	.shift = FD_JOB },
 	{ .name = "mutex",	.shift = FD_MUTEX },
 	{ .name	= "profile",	.shift = FD_PROFILE },
+	{ .name = "time",	.shift = FD_TIME },
 	{ .name = NULL, },
 };
 
diff --git a/options.c b/options.c
index 40f60ff..974df33 100644
--- a/options.c
+++ b/options.c
@@ -225,6 +225,15 @@ static int str_mem_cb(void *data, const char *mem)
 	return 0;
 }
 
+static int fio_clock_source_cb(void *data, const char *str)
+{
+	struct thread_data *td = data;
+
+	fio_clock_source = td->o.clocksource;
+	fio_time_init();
+	return 0;
+}
+
 static int str_lockmem_cb(void fio_unused *data, unsigned long *val)
 {
 	mlock_size = *val;
@@ -1217,6 +1226,29 @@ static struct fio_option options[FIO_MAX_OPTS] = {
 		.help	= "Ramp up time before measuring performance",
 	},
 	{
+		.name	= "clocksource",
+		.type	= FIO_OPT_STR,
+		.cb	= fio_clock_source_cb,
+		.off1	= td_var_offset(clocksource),
+		.help	= "What type of timing source to use",
+		.posval	= {
+			  { .ival = "gettimeofday",
+			    .oval = CS_GTOD,
+			    .help = "Use gettimeofday(2) for timing",
+			  },
+			  { .ival = "clock_gettime",
+			    .oval = CS_CGETTIME,
+			    .help = "Use clock_gettime(2) for timing",
+			  },
+#ifdef ARCH_HAVE_CPU_CLOCK
+			  { .ival = "cpu",
+			    .oval = CS_CPUCLOCK,
+			    .help = "Use CPU private clock",
+			  },
+#endif
+		},
+	},
+	{
 		.name	= "mem",
 		.alias	= "iomem",
 		.type	= FIO_OPT_STR,
diff --git a/time.c b/time.c
index 6397f20..5755b67 100644
--- a/time.c
+++ b/time.c
@@ -5,6 +5,7 @@
 
 static struct timeval genesis;
 static unsigned long ns_granularity;
+unsigned long long genesis_cycles;
 
 unsigned long long utime_since(struct timeval *s, struct timeval *e)
 {
@@ -150,10 +151,12 @@ int ramp_time_over(struct thread_data *td)
 	return 0;
 }
 
-static void fio_init time_init(void)
+void fio_init fio_time_init(void)
 {
 	int i;
 
+	fio_clock_init();
+
 	/*
 	 * Check the granularity of the nanosleep function
 	 */
@@ -177,6 +180,7 @@ static void fio_init time_init(void)
 void set_genesis_time(void)
 {
 	fio_gettime(&genesis, NULL);
+	genesis_cycles = get_cpu_clock();
 }
 
 void fill_start_time(struct timeval *t)
diff --git a/time.h b/time.h
new file mode 100644
index 0000000..61ad5d8
--- /dev/null
+++ b/time.h
@@ -0,0 +1,32 @@
+#ifndef FIO_TIME_H
+#define FIO_TIME_H
+
+/*
+ * Clock sources
+ */
+enum fio_cs {
+	CS_GTOD		= 1,
+	CS_CGETTIME,
+	CS_CPUCLOCK,
+};
+
+extern unsigned long long utime_since(struct timeval *, struct timeval *);
+extern unsigned long long utime_since_now(struct timeval *);
+extern unsigned long mtime_since(struct timeval *, struct timeval *);
+extern unsigned long mtime_since_now(struct timeval *);
+extern unsigned long time_since_now(struct timeval *);
+extern unsigned long mtime_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 *);
+extern void fio_gettime(struct timeval *, void *);
+extern void fio_gtod_init(void);
+extern void fio_clock_init(void);
+extern void fio_gtod_update(void);
+extern void set_genesis_time(void);
+extern int ramp_time_over(struct thread_data *);
+extern int in_ramp_time(struct thread_data *);
+extern unsigned long long genesis_cycles;
+extern void fio_time_init(void);
+
+#endif
--
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