aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2018-05-15 16:32:26 +0200
committerLukas Larsson <[email protected]>2018-05-15 16:36:48 +0200
commitd5dc5584884488c8fcb5710997a14c2c418692f3 (patch)
tree1058b4ef8953d6b814d898b890873ae2627a16d3
parent3b3e2f46841e3e86c991be92d62cbb0360ca80e3 (diff)
downloadotp-d5dc5584884488c8fcb5710997a14c2c418692f3.tar.gz
otp-d5dc5584884488c8fcb5710997a14c2c418692f3.tar.bz2
otp-d5dc5584884488c8fcb5710997a14c2c418692f3.zip
erts: Make cpu_timestamp use per thread on Linux
If we don't use per thread the value becomes completely nonsensical on systems with more than one scheduler. We keep the old solaris behaviour in order to support the option, but it only really works when using a single scheduler.
-rw-r--r--erts/aclocal.m48
-rw-r--r--erts/emulator/beam/erl_bif_trace.c4
-rw-r--r--erts/emulator/beam/erl_time_sup.c2
-rw-r--r--erts/emulator/beam/erl_trace.c14
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys.h10
-rw-r--r--lib/tools/doc/src/fprof.xml10
6 files changed, 21 insertions, 27 deletions
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4
index a4d09810bd..99b96eb5bc 100644
--- a/erts/aclocal.m4
+++ b/erts/aclocal.m4
@@ -2645,7 +2645,7 @@ case $erl_gethrvtime in
dnl Check if clock_gettime (linux) is working
dnl
- AC_MSG_CHECKING([if clock_gettime can be used to get process CPU time])
+ AC_MSG_CHECKING([if clock_gettime can be used to get thread CPU time])
save_libs=$LIBS
LIBS="-lrt"
AC_TRY_RUN([
@@ -2659,11 +2659,11 @@ case $erl_gethrvtime in
int i;
struct timespec tp;
- if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp) < 0)
+ if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp) < 0)
exit(1);
start = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
for (i = 0; i < 100; i++)
- clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
+ clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp);
stop = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
if (start == 0)
exit(4);
@@ -2686,7 +2686,7 @@ case $erl_gethrvtime in
case $erl_clock_gettime_cpu_time in
yes)
AC_DEFINE(HAVE_CLOCK_GETTIME_CPU_TIME,[],
- [define if clock_gettime() works for getting process time])
+ [define if clock_gettime() works for getting thread time])
LIBRT=-lrt
;;
cross)
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 1953f79d79..fd3400ab71 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -643,12 +643,12 @@ Eterm erts_internal_trace_3(BIF_ALIST_3)
SysTimespec tp;
int i;
- if (sys_get_proc_cputime(start, tp) < 0)
+ if (sys_get_cputime(start, tp) < 0)
goto error;
start = ((SysCpuTime)tp.tv_sec * 1000000000LL) +
(SysCpuTime)tp.tv_nsec;
for (i = 0; i < 100; i++)
- sys_get_proc_cputime(stop, tp);
+ sys_get_cputime(stop, tp);
stop = ((SysCpuTime)tp.tv_sec * 1000000000LL) +
(SysCpuTime)tp.tv_nsec;
if (start == 0) goto error;
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index 4f91d9ad07..29c698e34f 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -1860,7 +1860,7 @@ void erts_get_now_cpu(Uint* megasec, Uint* sec, Uint* microsec) {
SysCpuTime t;
SysTimespec tp;
- sys_get_proc_cputime(t, tp);
+ sys_get_cputime(t, tp);
*microsec = (Uint)(tp.tv_nsec / 1000);
t = (tp.tv_sec / 1000000);
*megasec = (Uint)(t % 1000000);
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 065a560b52..e9a413904b 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -625,20 +625,6 @@ erts_get_system_profile(void) {
return profile;
}
-
-#ifdef HAVE_ERTS_NOW_CPU
-# define GET_NOW(m, s, u) \
-do { \
- if (erts_cpu_timestamp) \
- erts_get_now_cpu(m, s, u); \
- else \
- get_now(m, s, u); \
-} while (0)
-#else
-# define GET_NOW(m, s, u) do {get_now(m, s, u);} while (0)
-#endif
-
-
static void
write_sys_msg_to_port(Eterm unused_to,
Port* trace_port,
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h
index 10adf80875..5bfe5a8e2d 100644
--- a/erts/emulator/sys/unix/erl_unix_sys.h
+++ b/erts/emulator/sys/unix/erl_unix_sys.h
@@ -292,6 +292,8 @@ erts_sys_perf_counter()
/*
* Functions for measuring CPU time
+ *
+ * Note that gethrvtime is time per process and clock_gettime is per thread.
*/
#if (defined(HAVE_GETHRVTIME) || defined(HAVE_CLOCK_GETTIME_CPU_TIME))
@@ -300,15 +302,15 @@ typedef struct timespec SysTimespec;
#if defined(HAVE_GETHRVTIME)
#define sys_gethrvtime() gethrvtime()
-#define sys_get_proc_cputime(t,tp) (t) = sys_gethrvtime(), \
- (tp).tv_sec = (time_t)((t)/1000000000LL), \
- (tp).tv_nsec = (long)((t)%1000000000LL)
+#define sys_get_cputime(t,tp) (t) = sys_gethrvtime(), \
+ (tp).tv_sec = (time_t)((t)/1000000000LL), \
+ (tp).tv_nsec = (long)((t)%1000000000LL)
int sys_start_hrvtime(void);
int sys_stop_hrvtime(void);
#elif defined(HAVE_CLOCK_GETTIME_CPU_TIME)
#define sys_clock_gettime(cid,tp) clock_gettime((cid),&(tp))
-#define sys_get_proc_cputime(t,tp) sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID,(tp))
+#define sys_get_cputime(t,tp) sys_clock_gettime(CLOCK_THREAD_CPUTIME_ID,(tp))
#endif
#endif
diff --git a/lib/tools/doc/src/fprof.xml b/lib/tools/doc/src/fprof.xml
index 4c9e48045e..72624bd33b 100644
--- a/lib/tools/doc/src/fprof.xml
+++ b/lib/tools/doc/src/fprof.xml
@@ -328,10 +328,16 @@
purposes. This option is only
allowed with the <c>start</c> option.</item>
<tag><c>cpu_time</c>| <c>{cpu_time, bool()}</c></tag>
- <item>The options <c>cpu_time</c> or <c>{cpu_time, true></c>
+ <item>The options <c>cpu_time</c> or <c>{cpu_time, true}</c>
makes the timestamps in the trace be in CPU time instead
of wallclock time which is the default. This option is
- only allowed with the <c>start</c> option.</item>
+ only allowed with the <c>start</c> option.
+ <warning><p>Getting correct values out of cpu_time can be difficult.
+ The best way to get correct values is to run using a single
+ scheduler and bind that scheduler to a specific CPU,
+ i.e. <c>erl +S 1 +sbt db</c>.</p>
+ </warning>
+ </item>
<tag><c>{procs, PidSpec}</c>| <c>{procs, [PidSpec]}</c></tag>
<item>Specifies which processes that shall be traced. If
this option is not given, the calling process is