2011-09-14 48 views
46

是否有一個簡單的方法/模塊正確在python中測量所用時間?我知道我可以簡單地打電話time.time()兩次,並採取差異,但如果系統時間發生變化,則會產生錯誤的結果。當然,這並不經常發生,但它確實表明我正在測量錯誤的東西。在python中測量所用時間

使用time.time()來衡量持續時間是非常迂迴的,當你想到它。您可以根據持續時間測量(由定時器執行)和已知絕對時間(手動設置或通過ntp設置)構建的兩個絕對時間測量值進行差異測量,您完全不感興趣。

那麼,有沒有辦法直接查詢這個「計時器時間」?我會想象它可以表示爲毫秒或微秒的值,它沒有有意義的絕對錶示(因此不需要用系統時間進行調整)。縱觀一下,這似乎正是System.nanoTime()在Java中所做的,但我沒有找到相應的Python函數,儘管它應該(硬件技術上)比time.time()更容易提供。

編輯:爲了避免混淆,並解決下面的答案:這不是關於夏令時的變化,我也不想CPU時間 - 我想要經過的物理時間。它不需要非常精細,甚至不是特別準確。只是因爲有人決定將系統時鐘設置爲不同的值,它不應該給我負面的持續時間,或持續時間超過幾個數量級(高於粒度)。下面介紹一下Python文檔說一下「了time.time()」:

"While this function normally returns non-decreasing values, it can return a lower value than a previous call if the system clock has been set back between the two calls"

這正是我想避免的東西,因爲它可以在時間計算導致像負值奇怪的事情。目前我可以解決這個問題,但我相信在可行的情況下學習使用適當的解決方案是一個不錯的主意,因爲有一天這些問題將會回來咬你。編輯2:一些研究表明你可以通過使用GetTickCount64()在Windows中獲得像我想要的系統時間獨立測量,在Linux下,你可以在times()的返回值中獲得它。但是,我仍然無法找到一個在Python中提供此功能的模塊。

+2

如果你想基準點的東西,你應該使用'timeit'。 – delnan

+1

相關:[我如何在python中獲得單調持續時間?](http://stackoverflow.com/questions/1205722/how-do-i-get-monotonic-time-durations-in-python) – jfs

回答

10

你似乎在尋找的是monotonic timer。 A monotonic time reference不會跳轉或倒退。

已經有幾次嘗試爲Python實現基於OS引用的跨平臺單調時鐘。 (Windows,POSIX和BSD完全不同)請參閱討論和this SO post中單調時間的一些嘗試。

晴,可以只使用os.times():

os.times()

返回浮動指示 積累點數(處理器或其他)倍的5元組,很快。這些項目是: 用戶時間,系統時間,兒童用戶時間,兒童系統時間, 以及自過去的固定點開始經過的實時時間。 請參閱Unix手冊頁次(2)或相應的Windows平臺API文檔。在Windows上,只有前兩項填充了 ,其他則爲零。

可用性:Unix上,視窗

但是,這並不在需要經過實時(五元組)在Windows上填寫。

如果您需要Windows支持,請考慮​​,您可以直接調用GetTickCount64(),如在this recipe中所做的那樣。

+1

我想知道爲什麼沒有人提議在Windows上向os.times添加第五元組值?似乎應該是可能的,因爲沒有指定參考點。 –

+0

@Mark Ransome:不是一個Winoze的傢伙,但也許是因爲類似於'GetTickCount64()'或其32版本的東西不在基準中爲cPython假設的核心Windows API中?即該平臺上的傳統支持?不知道,否則。單調時間參考是一個有用的功能。 –

24

要測量已用CPU時間,請查看time.clock()。這相當於Linux的times()用戶時間字段。

要進行基準測試,請使用timeit

如果平臺支持,datetime module,which is part of 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.Presumably返回的對象,系統時間可以有一個從NTP參考小的調整調整。 This should be slewed,更正爲applied gradually,但ntp同步節拍可以對非常小(毫秒或微秒)時間基準產生影響。

如果您想要某種分辨率,您也可以參考Alex Martelli's C function。我不會做太多的事情來重新發明輪子。準確的時間是基本的,大多數現代操作系統都做得很好。

編輯

根據您的澄清,這聽起來像你需要一個簡單的側檢查,如果系統的時鐘發生了變化。只是比較友好的,本地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精確到在互聯網毫秒,並且擁有2-32秒(233個皮秒)號決議表示分辨率。應該足夠好嗎?

請注意,NTP 64位數據結構will overflow in 2036 and every 136 years thereafter - 如果你真的想要一個強大的解決方案,爲更好地溢出檢查...

+1

+1迴轉信息,這可以緩解問題。不過,我並沒有追求更高的粒度。事實上,在我目前的應用程序中,秒會沒事的。 – Medo42

+2

我不認爲NTP服務器查詢是一個優雅的解決方案。畢竟,有一些專用硬件用於測量我想要構建的基本上每臺PC,並且可以通過Windows和Linux上的系統函數查詢 - 請參閱上面的新編輯。 – Medo42

+0

@ Medo42:你不需要對每個計時器實例進行ntp調用;只有在'time.time()'返回一個負數或意想不到的情況。 [Pyson's](http://stackoverflow.com/questions/7421641/measuring-elapsed-time-in-python/7423817#7423817)與'time.clock()'比較的方法具有優點。您可以使用類似的東西來觸發何時與外部來源進行比較。就我個人而言,操作系統時間對於我來說毫秒+時間就足夠了。使用硬件定時器有其自己的精度問題。 – dawg

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

使用UTC避免這些尷尬的時期時,時鐘偏移因夏令時。

至於使用替代方法而不是減去兩個時鐘,請注意,操作系統確實包含一個從PC中的硬件時鐘初始化的時鐘。現代操作系統的實施也將保持該時鐘與某些官方源同步,以便它不漂移。這比PC可能運行的任何間隔計時器準確得多。

+1

更準確 - 是的,從長遠來看。雖然在調整的時刻這個時鐘時間可能會表現得很奇怪(除非調整被調整,如drewk的回答所述)。我不需要長時間的高精度,但是我想要可靠的短期測量,不會因爲有人決定手動更改系統時間而產生負面或太大的間隔 - 有時會發生這種情況。 – Medo42

2

你在編輯狀態下,例如功能是兩個完全不同的事情:

  1. Linux的times()退貨流程次CPU毫秒。 Python的等價物是time.clock()或os.times()
  2. Windows GetTickCount64()返回系統正常運行時間。

雖然兩個不同的功能,無論是(潛在的)可以用來顯示系統時鐘有一個「打嗝」這些方法:

第一:

你可以採取既系統時間爲time.time(),CPU時間爲time.clock()。由於掛鐘時間總是大於或等於CPU時間,因此丟棄兩個讀數之間的間隔小於配對的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... 

二:

獲取系統的正常運行時間也是有希望的,如果你關心繫統的時鐘,因爲用戶復位不初始化在大多數情況下,正常運行時間滴答計數。 (我知道...)

現在更難的問題是:以獨立於平臺的方式獲得系統正常運行時間 - 特別是不產生新shell的系統正常運行時間 - 以次要的精度。嗯...

也許最好的選擇是psutilBrowsing the source,他們使用Windows的uptime = GetTickCount()/1000.00f;,使用BSD/OS X的sysctl "kern.boottime"等。不幸的是,這些都是1秒的分辨率。

+0

我在開始時也對times()感到困惑,但請閱讀您自己的鏈接手冊(特別是說「返回值」的部分)。該函數可用於查找填充到提供的結構中的進程時間,但它*返回一個系統時鐘的獨立時間量度。 – Medo42

+0

@ Medo42:你是對的,我的不好。 – 2011-09-23 21:52:34

+0

掛鐘時間是否總是大於CPU時間?我相信這只是單核系統的情況。 – Alex

2
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...