On 04/04/16 23:37, Nils Goroll wrote:
> I once optimized a CLOCK_REALTIME bound app by caching real time and 
> offsetting
> it with the TSC

Long story short, glibc does this ifdef HP_TIMING_AVAIL and my age-old wisdom
regarding mono vs. real does not hold any more - at least not on my own machine.

- Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt25-1 (2016-03-06) x86_64
- i7-4600M

In particular, glibc doesn't syscall (!), which I was complete unware of.

I expect this may look completely different on other platforms.


On 04/04/16 21:21, Devon H. O'Dell wrote:
> using 64-bit counters that represent the number of nanoseconds since the
> epoch.

insights from a trivial benchmark (patch attached) on my machine:

* real/mono overhead is <= ~5%

* ignoring the VTIM value, the double/uint64 overhead is negligible
  (as expected)

* with two arith ops per call (addition, division by 2), the double/uint64
  overhead is ~10 - ~15%

Please consider the usual disclaimers for synthetic benchmarks in a tight loop.

So this basically confirms dhos more realistic benchmarks:
- on this platform, optimizing for mono time does not make any sense
- the main potential is avoiding FP ops by representing time as an integer

Nils

        -

# default optimizer

varnish-cache/lib/libvarnish (master)$ cc -Wall -o foo -DTEST_DRIVER -I../..
-I../../include vtim.c vas.c -lm

varnish-cache/lib/libvarnish (master)$ ./foo bench
bench noop test value 0.000000
bench noop took 2.051ns per call

bench warmup test value 0.000000
bench warmup took 19.128ns per call

bench VTIM_mono test value 0.000000
bench VTIM_mono took 19.116ns per call
bench VTIM_mono_i test value 0.000000
bench VTIM_mono_i took 19.034ns per call
bench VTIM_real test value 0.000000
bench VTIM_real took 20.007ns per call
bench VTIM_real_i test value 0.000000
bench VTIM_real_i took 19.995ns per call

bench VTIM_mono test value 7008.426196
bench VTIM_mono took 25.131ns per call
bench VTIM_mono_i test value 7008644393743.000000
bench VTIM_mono_i took 21.817ns per call
bench VTIM_real test value 1460010972.766325
bench VTIM_real took 26.303ns per call
bench VTIM_real_i test value 1460010972992060672.000000
bench VTIM_real_i took 22.570ns per call

# -O6

varnish-cache/lib/libvarnish (master)$ cc -O6 -Wall -o foo -DTEST_DRIVER -I../..
-I../../include vtim.c vas.c -lm

varnish-cache/lib/libvarnish (master)$ ./foo bench
bench noop test value 0.000000
bench noop took 0.000ns per call

bench warmup test value 0.000000
bench warmup took 15.500ns per call

bench VTIM_mono test value 0.000000
bench VTIM_mono took 15.533ns per call
bench VTIM_mono_i test value 0.000000
bench VTIM_mono_i took 15.552ns per call
bench VTIM_real test value 0.000000
bench VTIM_real took 15.861ns per call
bench VTIM_real_i test value 0.000000
bench VTIM_real_i took 15.899ns per call

bench VTIM_mono test value 7624.422416
bench VTIM_mono took 20.277ns per call
bench VTIM_mono_i test value 7624605637622.000000
bench VTIM_mono_i took 18.319ns per call
bench VTIM_real test value 1460011588.673950
bench VTIM_real took 20.942ns per call
bench VTIM_real_i test value 1460011588860285696.000000
bench VTIM_real_i took 18.630ns per call
>From 8992fe9f50b96f2287da384acc5d3b16ad7cf25b Mon Sep 17 00:00:00 2001
From: Nils Goroll <[email protected]>
Date: Thu, 7 Apr 2016 08:17:00 +0200
Subject: [PATCH] uint64_t VTIM functions and a trivial benchmark

---
 include/vtim.h        |  4 +++
 lib/libvarnish/vtim.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)

diff --git a/include/vtim.h b/include/vtim.h
index 8db4fbe..a6d15f1 100644
--- a/include/vtim.h
+++ b/include/vtim.h
@@ -28,12 +28,16 @@
  *
  */
 
+#include <stdint.h>
+
 /* from libvarnish/vtim.c */
 #define VTIM_FORMAT_SIZE 30
 void VTIM_format(double t, char *p);
 double VTIM_parse(const char *p);
 double VTIM_mono(void);
 double VTIM_real(void);
+uint64_t VTIM_mono_i(void);
+uint64_t VTIM_real_i(void);
 void VTIM_sleep(double t);
 struct timespec VTIM_timespec(double t);
 struct timeval VTIM_timeval(double t);
diff --git a/lib/libvarnish/vtim.c b/lib/libvarnish/vtim.c
index 509ba9a..e0f81bb 100644
--- a/lib/libvarnish/vtim.c
+++ b/lib/libvarnish/vtim.c
@@ -111,6 +111,24 @@ VTIM_mono(void)
 #endif
 }
 
+uint64_t
+VTIM_mono_i(void)
+{
+#ifdef HAVE_GETHRTIME
+	return gethrtime();
+#elif  HAVE_CLOCK_GETTIME
+	struct timespec ts;
+
+	AZ(clock_gettime(CLOCK_MONOTONIC, &ts));
+	return (ts.tv_sec * 1e9 + ts.tv_nsec);
+#else
+	struct timeval tv;
+
+	AZ(gettimeofday(&tv, NULL));
+	return (tv.tv_sec * 1e6 + tv.tv_usec * 1e3);
+#endif
+}
+
 double
 VTIM_real(void)
 {
@@ -127,6 +145,22 @@ VTIM_real(void)
 #endif
 }
 
+uint64_t
+VTIM_real_i(void)
+{
+#ifdef HAVE_CLOCK_GETTIME
+	struct timespec ts;
+
+	AZ(clock_gettime(CLOCK_REALTIME, &ts));
+	return (ts.tv_sec * 1e9 + ts.tv_nsec);
+#else
+	struct timeval tv;
+
+	AZ(gettimeofday(&tv, NULL));
+	return (tv.tv_sec * 1e6 + tv.tv_usec * 1e3);
+#endif
+}
+
 void
 VTIM_format(double t, char *p)
 {
@@ -466,6 +500,58 @@ tst_delta()
 	}
 }
 
+static inline void noop(void) {}
+
+#define ben0(func, ts)						\
+	(void)func();
+
+#define ben1(func, ts)							\
+	(ts) += func();						\
+	(ts) /= 2;
+
+#define benchit(func, dt, tval) do {			\
+	const int niter = 1e7;			\
+	int i;						\
+							\
+	uint64_t t0, t1;				\
+	dt ts = 0;					\
+							\
+							\
+	t0 = VTIM_mono_i();				\
+	for (i=0; i < niter; i++) {			\
+		ben ## tval (func, ts)				\
+	}						\
+	t1 = VTIM_mono_i();				\
+								\
+	printf("bench %s test value %f\n", #func,		\
+	    (double)ts);					\
+									\
+	uintmax_t td = t1 - t0;					\
+									\
+	printf("bench %s took %ju.%03juns per call\n", #func,		\
+	    td / niter, (td / (niter / 1000)) % 1000);			\
+	} while(0)
+
+#define warmup VTIM_mono
+
+void
+bench()
+{
+	benchit(noop, double, 0);
+	printf("\n");
+	benchit(warmup, double, 0);
+	printf("\n");
+	benchit(VTIM_mono, double, 0);
+	benchit(VTIM_mono_i, uint64_t, 0);
+	benchit(VTIM_real, double, 0);
+	benchit(VTIM_real_i, uint64_t, 0);
+	printf("\n");
+	benchit(VTIM_mono, double, 1);
+	benchit(VTIM_mono_i, uint64_t, 1);
+	benchit(VTIM_real, double, 1);
+	benchit(VTIM_real_i, uint64_t, 1);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -475,6 +561,11 @@ main(int argc, char **argv)
 	char buf[BUFSIZ];
 	char buf1[BUFSIZ];
 
+	if (argc == 2 && strcmp(argv[1], "bench") == 0) {
+		bench();
+		exit (0);
+	}
+
 	AZ(setenv("TZ", "UTC", 1));
 	assert(sizeof t >= 8);
 
-- 
2.1.4

_______________________________________________
varnish-dev mailing list
[email protected]
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev

Reply via email to