How do I get monotonic time durations in python?
我想记录真实壁挂时间有多长。 目前我这样做:
1 2 3
| startTime = time.time()
someSQLOrSomething()
print"That took %.3f seconds" % (time.time() - startTime) |
但是如果在SQL查询(或其他任何东西)运行时调整时间,则会失败(产生不正确的结果)。
我不想只是对它进行基准测试。 我想在实时应用程序中记录它,以便查看实时系统的趋势。
我想要像clock_gettime(CLOCK_MONOTONIC,...)这样的东西,但是在Python中。 并且最好不必编写调用clock_gettime()的C模块。
-
好吧,我真的不知道实际调整的频率。我运行NTP。但是使用单声道时钟我不会遇到类似Oracle RAC错误的东西,如果时间倒退,它会重新启动系统。除了小的NTP调整,还有可以前后移动的闰秒。
-
S.Lott:不对。"闰秒是正面或负面的一秒调整[...]"。抬头看起来很简单。这是维基百科上"闰秒"文章的第一句话。因此,当添加闰秒时,NTP将向后调整系统时间(因为您的系统速度很快。它没有计算23:59:60),这意味着基于time.time()的测量可能是负面的。相信我,许多Oracle服务器由于我上一年新提到的错误而重新启动。我只是以Oracle为例,某些程序无法处理时间重新调整。
-
我不知道为什么(未修补)Oracle 10会这样做。它就是这样,甲骨文(该公司)证实了这一点。
-
只是想在这里添加一个我们遇到的用例的评论。在由多个vmware系统组成的我们的设置中,我们注意到客户虚拟机中的时间"调整"确实发生得足够频繁,尤其是主机的负载平均值。高。这导致像supervisord这样的东西看起来依赖于time.time()崩溃,导致它启动的进程孤立。我们通过应用补丁修复了这个问题 - github.com/Supervisor/supervisor/pull/468
-
@Thomas:从理论上讲,可能存在负闰秒。在实践中,所有闰秒都是积极的。见闰秒:它的历史和可能的未来。
该函数非常简单,您可以使用ctypes来访问它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #!/usr/bin/env python
__all__ = ["monotonic_time"]
import ctypes, os
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_, os.strerror(errno_))
return t.tv_sec + t.tv_nsec * 1e-9
if __name__ =="__main__":
print monotonic_time() |
-
哇。删除"自我"。它工作得很好。非常令人印象深刻。它需要ctypes作为Python 2.4的附加组件,但它会做得很好。谢谢。
-
哦,CLOCK_MONOTONIC在FreeBSD上似乎是4,在Linux上似乎是1。
-
好的解决方案你有没有理由使用ctypes.pointer而不是ctypes.byref?
-
@Thomas:修正了,删除自@Kiv:byref应该工作,现在不能测试,但它应该做的伎俩。我不记得byref()什么时候不起作用,所以我走了安全路径。
-
您是否(或其他具有编辑权限的人)可以编辑此答案并将10e9更改为1e9,因为Mitch在其他答案中建议?
-
我添加了受此启发的代码,并且实际上在这里使用:code.google.com/p/anacrolix/source/browse/projects/pimu/…
-
使用CLOCK_MONOTONIC_RAW==4(自Linux 2.6.28;特定于Linux)以避免NTP调整。
-
为什么使用CLOCK_MONOTONIC_RAW而不是CLOCK_PROCESS_CPUTIME_ID?有什么区别? (此处的文档:man7.org/linux/man-pages/man2/clock_gettime.2.html)。这里使用CLOCK_PROCESS_CPUTIME_ID的C示例:stackoverflow.com/questions/6749621/…
-
回答我自己的问题(python.org/dev/peps/pep-0418/#process-time):CLOCK_PROCESS_CPUTIME_ID:"无法设置处理时间。它不是单调的:时钟在进程空闲时停止。"在睡眠或暂停期间不计算。根据这项研究和上面的链接,我想使用CLOCK_HIGHRES(也包括暂停时间)或者CLOCK_MONOTONIC我认为,在Linux上"转换"(我认为这意味着在这里调整它的准确性。 ..像校准???)来源:python.org/dev/peps/pep-0418/#monotonic-clocks。
-
我再次改变主意,我选择CLOCK_MONOTONIC_RAW,就像你所做的那样,因为它"类似于CLOCK_MONOTONIC,但可以访问不受NTP影响的基于硬件的原始时间[网络时间协议]调整或由adjtime(3)执行的增量调整。" (man7.org/linux/man-pages/man2/clock_gettime.2.html)。所以,我已经回答了我自己的问题,提供了一些帮助他人的有价值的链接,并且完整地接受了你选择的时钟并且最喜欢那个时钟,用于基本的低级时间戳和精确的间隔测量。
-
感谢@ArminRonacher的回答,我已将其合并到我在此发布的Windows / Linux兼容模块中:stackoverflow.com / a / 38319607/4561887
现在,在Python 3.3中你将使用time.monotonic。
-
在CPython中,我假设它在内部使用CLOCK_MONOTONIC而不是CLOCK_MONOTONIC_RAW,后者在Python 3.3中甚至不可用。
-
@ A-B-B:time模块知道CLOCK_MONOTONIC_RAW,尽管我没有看到它。您可以通过ctypes定义使用它的时钟,即使在Python 2.7上也是如此
-
如果我正在阅读正确的文档,那么在Python 3.3中你可以通过调用time.clock_gettime(time.CLOCK_MONOTONIC_RAW)获得CLOCK_MONOTONIC_RAW,这很好,所以当你用它来测量小的时间间隔时,你永远不会在网络更新时间时引入错误 通过NTP(网络时间协议)调整。 Python时间参考:docs.python.org/3/library/time.html#time.CLOCK_MONOTONIC_RAW。 < - 注意:仅适用于UNIX / LINUX。 对于Windows,只需调用time.clock(),因为它使用QueryPerformanceCounter(),因此已经具有微秒或更高的分辨率。
正如在这个问题中指出的那样,避免在Linux上进行NTP重新调整需要CLOCK_MONOTONIC_RAW。 在Linux上定义为4(从2.6.28开始)。
在Python的C头中容易地获取正确的常量#defined是很棘手的; 有h2py,但这并没有真正帮助你在运行时获得值。
-
我相信所选择的答案是不正确的,并没有解释跳跃,请参阅我的评论。 CLOCK_MONOTONIC和CLOCK_MONOTONIC_RAW都是单调的,它们不同的唯一方法是前者使用NTP校正硬件时钟速度。
以下是我在Python 2.7中获得单调时间的方法:
安装monotonic包:
然后在Python中:
1 2 3 4 5
| import monotonic; mtime = monotonic.time.time #now mtime() can be used in place of time.time()
t0 = mtime()
#...do something
elapsed = mtime()-t0 #gives correct elapsed time, even if system clock changed. |
time.monotonic()可能有用:
Return the value (in fractional seconds) of a monotonic clock, i.e. a clock that cannot go backwards. The clock is not affected by system clock updates. The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid.