有没有办法在Python中以高精度测量时间---比一秒更精确?我怀疑是否有跨平台的方式来做到这一点;我对Unix上的高精度时间感兴趣,特别是在Sun SPARC机器上运行的Solaris。
timeit似乎能够进行高精度的时间测量,但我不想测量代码片段需要多长时间,而是想直接访问时间值。
答案 0 :(得分:43)
标准time.time()
函数提供亚秒级精度,但该精度因平台而异。对于Linux和Mac,精度为+-
1微秒或0.001毫秒。由于进程中断导致时钟实现问题,Windows上的Python使用+-
16毫秒的精度。如果您正在测量执行时间,timeit
模块可以提供更高的分辨率。
>>> import time
>>> time.time() #return seconds from epoch
1261367718.971009
Python 3.7为time
模块引入了提供更高分辨率的新功能:
>>> import time
>>> time.time_ns()
1530228533161016309
>>> time.time_ns() / (10 ** 9) # convert to floating-point seconds
1530228544.0792289
答案 1 :(得分:22)
Python努力为您的平台使用最精确的时间函数来实现time.time()
:
/* Implement floattime() for various platforms */
static double
floattime(void)
{
/* There are three ways to get the time:
(1) gettimeofday() -- resolution in microseconds
(2) ftime() -- resolution in milliseconds
(3) time() -- resolution in seconds
In all cases the return value is a float in seconds.
Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
fail, so we fall back on ftime() or time().
Note: clock resolution does not imply clock accuracy! */
#ifdef HAVE_GETTIMEOFDAY
{
struct timeval t;
#ifdef GETTIMEOFDAY_NO_TZ
if (gettimeofday(&t) == 0)
return (double)t.tv_sec + t.tv_usec*0.000001;
#else /* !GETTIMEOFDAY_NO_TZ */
if (gettimeofday(&t, (struct timezone *)NULL) == 0)
return (double)t.tv_sec + t.tv_usec*0.000001;
#endif /* !GETTIMEOFDAY_NO_TZ */
}
#endif /* !HAVE_GETTIMEOFDAY */
{
#if defined(HAVE_FTIME)
struct timeb t;
ftime(&t);
return (double)t.time + (double)t.millitm * (double)0.001;
#else /* !HAVE_FTIME */
time_t secs;
time(&secs);
return (double)secs;
#endif /* !HAVE_FTIME */
}
}
(来自http://svn.python.org/view/python/trunk/Modules/timemodule.c?revision=81756&view=markup)
答案 2 :(得分:19)
David的帖子试图显示Windows上的时钟分辨率。我对他的输出感到困惑,所以我写了一些代码,表明我的Windows 8 x64笔记本电脑上的time.time()
分辨率为1毫秒:
# measure the smallest time delta by spinning until the time changes
def measure():
t0 = time.time()
t1 = t0
while t1 == t0:
t1 = time.time()
return (t0, t1, t1-t0)
samples = [measure() for i in range(10)]
for s in samples:
print s
哪个输出:
(1390455900.085, 1390455900.086, 0.0009999275207519531)
(1390455900.086, 1390455900.087, 0.0009999275207519531)
(1390455900.087, 1390455900.088, 0.0010001659393310547)
(1390455900.088, 1390455900.089, 0.0009999275207519531)
(1390455900.089, 1390455900.09, 0.0009999275207519531)
(1390455900.09, 1390455900.091, 0.0010001659393310547)
(1390455900.091, 1390455900.092, 0.0009999275207519531)
(1390455900.092, 1390455900.093, 0.0009999275207519531)
(1390455900.093, 1390455900.094, 0.0010001659393310547)
(1390455900.094, 1390455900.095, 0.0009999275207519531)
这是一种平均增量的1000个样本的方法:
reduce( lambda a,b:a+b, [measure()[2] for i in range(1000)], 0.0) / 1000.0
连续两次运行的输出:
0.001
0.0010009999275207519
因此,我的Windows 8 x64上的time.time()
分辨率为1毫秒。
time.clock()
上的类似运行会返回0.4微秒的分辨率:
def measure_clock():
t0 = time.clock()
t1 = time.clock()
while t1 == t0:
t1 = time.clock()
return (t0, t1, t1-t0)
reduce( lambda a,b:a+b, [measure_clock()[2] for i in range(1000000)] )/1000000.0
返回:
4.3571334791658954e-07
哪个是〜0.4e-06
关于time.clock()
的一个有趣的事情是,它返回自首次调用方法以来的时间,因此如果您想要微秒分辨率的挂起时间,您可以执行以下操作:
class HighPrecisionWallTime():
def __init__(self,):
self._wall_time_0 = time.time()
self._clock_0 = time.clock()
def sample(self,):
dc = time.clock()-self._clock_0
return self._wall_time_0 + dc
(这可能会在一段时间后漂移,但你偶尔可以纠正这个问题,例如dc > 3600
会每小时纠正一次)
答案 3 :(得分:14)
您还可以使用time.clock()它计算Unix上进程使用的时间以及自Windows首次调用它以来的时间。它比time.time()更精确。
这是衡量表现的常用功能。
致电
import time
t_ = time.clock()
#Your code here
print 'Time in function', time.clock() - t_
编辑:Ups,我想念你的问题,因为你想知道时间,而不是花时间......
答案 4 :(得分:7)
如果Python 3是一个选项,您有两种选择:
time.perf_counter
始终在您的平台上使用最准确的时钟。它确实包括在流程之外花费的时间。time.process_time
返回CPU时间。 NOT 包括在流程之外花费的时间。两者之间的差异可以显示为:
WEB-INF
哪个输出:
from time import (
process_time,
perf_counter,
sleep,
)
print(process_time())
sleep(1)
print(process_time())
print(perf_counter())
sleep(1)
print(perf_counter())
答案 5 :(得分:4)
time.clock()
在Windows上有13个小数点,但在Linux上只有两个小数点。
time.time()
在Linux上有17位小数,在Windows上有16位小数,但实际精度不同。
我不同意time.clock()
应该用于Unix / Linux基准测试的文档。它不够精确,所以使用的计时器取决于操作系统。
在Linux上,时间分辨率在time.time()
:
>>> time.time(), time.time()
(1281384913.4374139, 1281384913.4374161)
在Windows上,时间函数似乎使用最后一个被叫号码:
>>> time.time()-int(time.time()), time.time()-int(time.time()), time.time()-time.time()
(0.9570000171661377, 0.9570000171661377, 0.0)
即使我在Windows中的不同行上编写调用,它仍会返回相同的值,因此实际精度较低。
因此,在严格的测量中,必须进行平台检查(import platform, platform.system()
)才能确定是使用time.clock()
还是time.time()
。
(在Windows 7和Ubuntu 9.10上使用python 2.6和3.1测试)
答案 6 :(得分:4)
Python 3.7引入了6个具有纳秒分辨率的新时间函数,例如代替time.time()
,您可以使用time.time_ns()
:
import time
print(time.time())
# 1522915698.3436284
print(time.time_ns())
# 1522915698343660458
中描述了这6个函数
time.clock_gettime_ns(clock_id)
time.clock_settime_ns(clock_id, time:int)
time.monotonic_ns()
time.perf_counter_ns()
time.process_time_ns()
time.time_ns()
这些函数类似于没有_ns后缀的版本,但是 以Python int返回一些纳秒数。
答案 7 :(得分:2)
comment left by tiho on Mar 27 '14 at 17:21应该是它自己的答案:
为了避免特定于平台的代码,请使用timeit.default_timer()
答案 8 :(得分:1)
我发现Windows 10专业版和教育版之间的time.time()分辨率不同。
在Windows 10 Professional计算机上,分辨率为1毫秒。 在Windows 10教育版计算机上,分辨率为16毫秒。
幸运的是,有一个工具可以提高Windows中Python的时间分辨率: https://vvvv.org/contribution/windows-system-timer-tool
使用此工具,无论Windows版本如何,我都能实现1 ms的分辨率。在执行Python代码时,您需要使其保持运行状态。
答案 9 :(得分:1)
对于卡在Windows(版本> = Server 2012或Win 8)和python 2.7上的用户,
import ctypes
class FILETIME(ctypes.Structure):
_fields_ = [("dwLowDateTime", ctypes.c_uint),
("dwHighDateTime", ctypes.c_uint)]
def time():
"""Accurate version of time.time() for windows, return UTC time in term of seconds since 01/01/1601
"""
file_time = FILETIME()
ctypes.windll.kernel32.GetSystemTimePreciseAsFileTime(ctypes.byref(file_time))
return (file_time.dwLowDateTime + (file_time.dwHighDateTime << 32)) / 1.0e7
答案 10 :(得分:1)
以下是Windows的python 3解决方案,它基于 CyberSnoopy 在上面发布的答案(使用 GetSystemTimePreciseAsFileTime )。我们从 jfs
借用了一些代码Python datetime.utcnow() returning incorrect datetime
并获得精确的时间戳(Unix时间)(以微秒为单位)
#! python3
import ctypes.wintypes
def utcnow_microseconds():
system_time = ctypes.wintypes.FILETIME()
#system call used by time.time()
#ctypes.windll.kernel32.GetSystemTimeAsFileTime(ctypes.byref(system_time))
#getting high precision:
ctypes.windll.kernel32.GetSystemTimePreciseAsFileTime(ctypes.byref(system_time))
large = (system_time.dwHighDateTime << 32) + system_time.dwLowDateTime
return large // 10 - 11644473600000000
for ii in range(5):
print(utcnow_microseconds()*1e-6)
参考文献
https://docs.microsoft.com/en-us/windows/win32/sysinfo/time-functions
https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
https://support.microsoft.com/en-us/help/167296/how-to-convert-a-unix-time-t-to-a-win32-filetime-or-systemtime
答案 11 :(得分:0)
最初的问题专门针对Unix,但在Windows上涉及了多个答案,因此Windows上的信息具有误导性。 Windows上的默认计时器分辨率为15.6ms you can verify here.
使用来自cod3monk3y的稍微修改的脚本,我可以证明Windows计时器分辨率默认为〜15毫秒。我正在使用here可用的工具来修改分辨率。
脚本:
import time
# measure the smallest time delta by spinning until the time changes
def measure():
t0 = time.time()
t1 = t0
while t1 == t0:
t1 = time.time()
return t1-t0
samples = [measure() for i in range(30)]
for s in samples:
print(f'time delta: {s:.4f} seconds')
这些结果收集在运行python 3.7 64位的Windows 10 pro 64位上。
答案 12 :(得分:0)
在使用 “两种不同方法的方法” 的同一个win10 OS系统上,似乎存在一个近似的 “ 500 ns” 时差。如果您关心纳秒级精度,请在下面查看我的代码。
对代码的修改基于用户cod3monk3y
和Kevin S
的代码。
操作系统:python 3.7.3 (default, date, time) [MSC v.1915 64 bit (AMD64)]
def measure1(mean):
for i in range(1, my_range+1):
x = time.time()
td = x- samples1[i-1][2]
if i-1 == 0:
td = 0
td = f'{td:.6f}'
samples1.append((i, td, x))
mean += float(td)
print (mean)
sys.stdout.flush()
time.sleep(0.001)
mean = mean/my_range
return mean
def measure2(nr):
t0 = time.time()
t1 = t0
while t1 == t0:
t1 = time.time()
td = t1-t0
td = f'{td:.6f}'
return (nr, td, t1, t0)
samples1 = [(0, 0, 0)]
my_range = 10
mean1 = 0.0
mean2 = 0.0
mean1 = measure1(mean1)
for i in samples1: print (i)
print ('...\n\n')
samples2 = [measure2(i) for i in range(11)]
for s in samples2:
#print(f'time delta: {s:.4f} seconds')
mean2 += float(s[1])
print (s)
mean2 = mean2/my_range
print ('\nMean1 : ' f'{mean1:.6f}')
print ('Mean2 : ' f'{mean2:.6f}')
measure1结果:
nr, td, t0
(0, 0, 0)
(1, '0.000000', 1562929696.617988)
(2, '0.002000', 1562929696.6199884)
(3, '0.001001', 1562929696.620989)
(4, '0.001001', 1562929696.62199)
(5, '0.001001', 1562929696.6229906)
(6, '0.001001', 1562929696.6239917)
(7, '0.001001', 1562929696.6249924)
(8, '0.001000', 1562929696.6259928)
(9, '0.001001', 1562929696.6269937)
(10, '0.001001', 1562929696.6279945)
...
measure2结果:
nr, td , t1, t0
(0, '0.000500', 1562929696.6294951, 1562929696.6289947)
(1, '0.000501', 1562929696.6299958, 1562929696.6294951)
(2, '0.000500', 1562929696.6304958, 1562929696.6299958)
(3, '0.000500', 1562929696.6309962, 1562929696.6304958)
(4, '0.000500', 1562929696.6314962, 1562929696.6309962)
(5, '0.000500', 1562929696.6319966, 1562929696.6314962)
(6, '0.000500', 1562929696.632497, 1562929696.6319966)
(7, '0.000500', 1562929696.6329975, 1562929696.632497)
(8, '0.000500', 1562929696.633498, 1562929696.6329975)
(9, '0.000500', 1562929696.6339984, 1562929696.633498)
(10, '0.000500', 1562929696.6344984, 1562929696.6339984)
最终结果:
平均值1:0.001001#(measure1函数)
平均值2:0.000550#(measure2函数)
答案 13 :(得分:-1)
def start(self):
sec_arg = 10.0
cptr = 0
time_start = time.time()
time_init = time.time()
while True:
cptr += 1
time_start = time.time()
time.sleep(((time_init + (sec_arg * cptr)) - time_start ))
# AND YOUR CODE .......
t00 = threading.Thread(name='thread_request', target=self.send_request, args=([]))
t00.start()