繁体   English   中英

在python中测量经过的时间

[英]Measuring elapsed time in python

有没有一种简单的方法/模块可以正确测量python中的经过时间? 我知道我可以简单地调用time.time()两次并获取差异,但是如果系统时间发生更改,则会产生错误的结果。 诚然,这种情况并不经常发生,但它确实表明我测量的是错误的东西。

当您考虑它时,使用time.time()来测量持续时间是令人难以置信的迂回。 您获取两个绝对时间测量的差异,这两个绝对时间测量依次由持续时间测量(由计时器执行)和已知的绝对时间(手动或通过 ntp 设置)构成,您根本不感兴趣。

那么,有没有办法直接查询这个“定时器时间”呢? 我想它可以表示为没有有意义的绝对表示的毫秒或微秒值(因此不需要用系统时间进行调整)。 环顾四周,这似乎正是System.nanoTime()在 Java 中所做的,但我没有找到相应的 Python 函数,尽管它应该(硬件技术上)比time.time()更容易提供。

编辑:为避免混淆并解决以下答案:这与 DST 更改无关,我也不想要 CPU 时间 - 我想要经过的物理时间。 它不需要非常细粒度,甚至不需要特别准确。 它只是不应该给我负持续时间,或者持续时间相差几个数量级(高于粒度),只是因为有人决定将系统时钟设置为不同的值。 以下是 Python 文档关于 'time.time()' 的说明:

“虽然此函数通常返回非递减值,但如果系统时钟已在两次调用之间调回,则它可以返回比先前调用更低的值”

这正是我想要避免的,因为它会导致奇怪的事情,比如时间计算中的负值。 我现在可以解决这个问题,但我相信在可行的情况下学习使用正确的解决方案是个好主意,因为有一天这些杂物会回来咬你。

Edit2:一些研究表明,您可以通过使用 GetTickCount64() 在 Windows 中获得我想要的系统时间独立测量,在 Linux 下,您可以在 times() 的返回值中获得它。 但是,我仍然找不到在 Python 中提供此功能的模块。

要测量经过的 CPU 时间,请查看time.clock() 这相当于 Linux 的times()用户时间字段。

对于基准测试,请使用timeit

datetime 模块是 Python 2.3+ 的一部分,如果平台支持,它也有微秒时间。

例子:

>>> import datetime as dt
>>> n1=dt.datetime.now()
>>> n2=dt.datetime.now()
>>> (n2-n1).microseconds
678521
>>> (n2.microsecond-n1.microsecond)/1e6
0.678521
ie, it took me .678521 seconds to type the second n2= line -- slow
>>> n1.resolution
datetime.timedelta(0, 0, 1)
1/1e6 resolution is claimed.

如果您担心系统时间更改(从 DS -> ST),只需检查 datetime 返回的对象。据推测,系统时间可能会从NTP参考调整中进行小幅调整。 这应该被调整,并且逐渐应用更正,但是 ntp 同步节拍可能对非常小的(毫秒或微秒)时间参考产生影响。

如果您需要该分辨率的内容,也可以参考Alex Martelli 的 C 函数 我不会走得太远去重新发明轮子。 准确的时间是基本的,大多数现代操作系统都做得很好。

编辑

根据您的说明,听起来您需要简单地检查系统时钟是否已更改。 只需比较一个友好的本地 ntp 服务器:

import socket
import struct
import time

ntp="pool.ntp.org"   # or whatever ntp server you have handy

client = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
data = '\x1b' + 47 * '\0'
client.sendto( data, ( ntp, 123 ))
data, address = client.recvfrom( 1024 )
if data:
    print 'Response received from:', address
    t = struct.unpack( '!12I', data )[10]
    t -= 2208988800L #seconds since Epoch
    print '\tTime=%s' % time.ctime(t)

NTP 在 Internet 上精确到毫秒,并具有 2-32 秒(233 皮秒)的分辨率表示分辨率。 应该够好吗?

请注意,NTP 64 位数据结构将在 2036 年以及之后每 136 年溢出一次——如果你真的想要一个强大的解决方案,最好检查一下是否溢出......

Python 3.3 在标准库中添加了一个单调计时器,这正是我想要的。 感谢 Paddy3118 在“如何在 python 中获得单调持续时间?”中指出这一点。 .

您似乎正在寻找的是一个单调的计时器 单调时间参考不会跳跃或倒退。

基于 Python 的 OS 参考,已经多次尝试为 Python 实现跨平台单调时钟。 (Windows、POSIX 和 BSD 完全不同)请参阅此 SO 帖子中的讨论和单调时间的一些尝试。

大多数情况下,您可以只使用 os.times():

os.times()

返回一个浮点数的 5 元组,以秒为单位表示累积(处理器或其他)时间。 这些项目是:用户时间、系统时间、孩子的用户时间、孩子的系统时间,以及从过去的固定点开始经过的实时时间,按此顺序。 请参阅 Unix 手册页 times(2) 或相应的 Windows 平台 API 文档。 在 Windows 上,仅填充前两项,其他项为零。

可用性:Unix、Windows

但这并不能填充 Windows 上所需的经过的实时时间(第五个元组)。

如果您需要 Windows 支持,请考虑ctypes ,您可以直接调用 GetTickCount64(),就像在这个秘籍中所做的那样。

>>> import datetime
>>> t1=datetime.datetime.utcnow()
>>> t2=datetime.datetime.utcnow()
>>> t2-t1
datetime.timedelta(0, 8, 600000)

使用 UTC 可以避免由于夏令时而导致时钟偏移的那些尴尬时期。

至于使用替代方法而不是减去两个时钟,请注意操作系统确实包含一个时钟,该时钟是从 PC 中的硬件时钟初始化的。 现代操作系统实现还将使该时钟与某些官方来源保持同步,以使其不会漂移。 这比 PC 可能运行的任何间隔计时器都要准确得多。

from datetime import datetime
start = datetime.now()
print 'hello'
end = datetime.now()
delta = end-start
print type(delta)
<type 'datetime.timedelta'>
import datetime
help(datetime.timedelta)
...elapsed seconds and microseconds...

您在编辑中陈述的示例函数是两个完全不同的东西:

  1. Linux times()以 CPU 毫秒为单位返回进程时间。 Python 的等价物是 time.clock() 或os.times()
  2. Windows GetTickCount64()返回系统正常运行时间。

尽管有两个不同的功能,但两者(可能)都可用于显示系统时钟,该系统时钟通过以下方法“打嗝”:

第一的:

您可以使用time.time()来获取系统时间,也可以使用time.clock()来获取 CPU 时间。 由于挂钟时间总是大于或等于 CPU 时间,因此丢弃两次time.time()读数之间的间隔小于配对time.clock()检查读数的任何测量。

例子:

t1=time.time()
t1check=time.clock()

# your timed event...    

t2=time.time()
t2check=time.clock()

if t2-t1 < t2check - t1check:
    print "Things are rotten in Denmark"
    # discard that sample
else:
    # do what you do with t2 - t1... 

第二:

如果您担心系统的时钟,那么获得系统正常运行时间也很有希望,因为在大多数情况下,用户重置不会重置正常运行时间滴答计数。 (我知道...)

现在更难的问题是:以独立于平台的方式获得系统正常运行时间——尤其是在不产生新外壳的情况下——以亚秒级的精度。 嗯……

最好的选择可能是psutil 浏览源代码,他们使用uptime = GetTickCount() / 1000.00f; 对于 Windows 和sysctl "kern.boottime"对于 BSD / OS X 等。不幸的是,这些都是 1 秒的分辨率。

在 Python 3.3+ 中使用 time.monotonic 后,我发现它在 Mac 上运行良好,永远不会倒退。 在 Windows 上,它使用 GetTickCount64() 它很少会向后退大量(出于我的程序超过 5.0 的目的)添加包装器可以防止单调后退:

with a_lock:
    original_value = time.monotonic()
    if original_value < last_value:
        # You can post a metric here to monitor frequency and size of backward jumps
        offset = last_value - original_value
    last_value = original_value
    return offset + original_value

它多久倒退一次? 在数以百万计的机器上,可能会在数天之内发生几次,然后再一次,仅在 Windows 上。 抱歉,我没有跟踪哪些版本的 Windows。 如果人们愿意,我可以稍后更新。

您可以在 Python 标准库中使用 time 模块的perf_counter函数:

from datetime import timedelta
from time import perf_counter

startTime = perf_counter()
CallYourFunc()
finishedTime = perf_counter()
duration = timedelta(seconds=(finishedTime - startTime))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM