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