from datetime import datetime as dt
from itertools import tee
from warnings import warn
-from sys import stderr, version_info, exit as sys_exit
+from sys import stderr, platform, version_info, exit as sys_exit
from os import getpid, kill, _exit as brutal_exit_function_DO_NOT_USE
import signal
def get_perf_counter():
- """ returns time.perf_counter or time.clock depending on python version
+ """ return the best monotonic clock for performance measure
- before py 3.3: return function :py:function:`time.clock`
+ returned clocks are monotonic and measure "absoulte"/wall-clock time
+ differences (as opposed to time processor spends on the particular python
+ code, so sleep(1) should result in a perf counter diff of 1).
+
+ before py 3.3: return monotonic clock from linux system
after that: returns function :py:function:`time.perf_counter`
- .. warn:: these will behave differently, so do not make assumption on change
- or time during sleep or what 0 value means
+ .. warn:: absolute values mean nothing, only differences between calls!
For simple single-command use cases: use ipython's %timeit magic command.
"""
if version_info.major == 2:
- return time.clock
+ if platform.startswith('linux'):
+ return monotonic_clock_py2()
+ else:
+ return time.time
elif version_info.major == 3 and version_info.minor < 3:
return time.clock
else:
return time.perf_counter
+
+
+def monotonic_clock_py2():
+ """ get a monotonic clock in py2 using ctypes and clock_gettime
+
+ copied from:
+ https://stackoverflow.com/questions/1205722/
+ how-do-i-get-monotonic-time-durations-in-python
+ """
+
+ import ctypes
+ from os import strerror
+ CLOCK_MONOTONIC_RAW = 4 # see <linux/time.h>
+
+ class timespec(ctypes.Structure):
+ _fields_ = [
+ ('tv_sec', ctypes.c_long),
+ ('tv_nsec', ctypes.c_long)
+ ]
+
+ librt = ctypes.CDLL('librt.so.1', use_errno=True)
+ clock_gettime = librt.clock_gettime
+ clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
+
+ def monotonic_time():
+ t = timespec()
+ if clock_gettime(CLOCK_MONOTONIC_RAW , ctypes.pointer(t)) != 0:
+ errno_ = ctypes.get_errno()
+ raise OSError(errno_, strerror(errno_))
+ return t.tv_sec + t.tv_nsec * 1e-9
+
+ return monotonic_time