2009-07-30 11 views
45

Chcę się zalogować, jak długo trwa rzeczywisty czas na ścianie. Obecnie robię tak:Jak uzyskać monotoniczny czas trwania w python?

startTime = time.time() 
someSQLOrSomething() 
print "That took %.3f seconds" % (time.time() - startTime) 

Ale to się nie powiedzie (uzyskiwanie nieprawidłowych wyników), jeśli czas jest regulowana podczas kwerendy SQL (lub cokolwiek to jest) jest uruchomiony.

Nie chcę po prostu porównywać go. Chcę go zarejestrować w aplikacji na żywo, aby zobaczyć trendy w systemie na żywo.

Chcę coś takiego jak clock_gettime (CLOCK_MONOTONIC, ...), ale w Pythonie. A najlepiej bez pisania modułu C, który wywołuje clock_gettime().

+6

No ja nie wiem jak często jest to właściwie dostosowane. Prowadzę NTP. Ale z mononicznym zegarem nie będę musiał wpadać na takie rzeczy, jak błąd Oracle RAC, w którym zrestartował system, jeśli czas był ustawiony wstecz. Poza niewielkimi korektami NTP, istnieją sekundy przestępne, które można cofać i przewijać dalej. – Thomas

+7

S.Lott: niepoprawny. "Sekunda skokowa to dodatnia lub ujemna korekcja jednej sekundy [...]". Przejrzenie się jest banalne. To pierwsze zdanie na temat artykułu "Leap second" na Wikipedii. Kiedy więc dodana zostanie sekunda przejściowa, NTP ponownie ustawi czas systemowy w tył (ponieważ twój system jest szybki, nie liczył się 23:59:60), co oznacza, że ​​pomiar oparty na time.time() może być ujemny. Zaufajcie mi, wiele serwerów Oracle zostało zrestartowanych z powodu błędu, o którym wspomniałem powyżej w poprzednim numerze. Po prostu użyłem Oracle jako przykładu, w którym niektóre programy nie radzą sobie z korektami czasu. – Thomas

+0

Nie wiem, dlaczego (niezałatwiony) Oracle 10 to robi. Po prostu tak jest i Oracle (firma) to potwierdza. – Thomas

Odpowiedz

71

Funkcja ta jest na tyle prosta, że ​​można użyć ctypes do niego dostęp:

#!/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() 
+0

Wow. Usuń "self". i działało idealnie. Bardzo imponujące. Wymaga to ctypów, które są dodatkiem do Pythona 2.4, ale będzie całkiem ładnie. Dzięki. – Thomas

+0

Oh, a CLOCK_MONOTONIC wydaje się być 4 na FreeBSD i 1 na Linux. – Thomas

+0

Ładne rozwiązanie. Czy istnieje jakiś powód użycia ctypes.pointer zamiast ctypes.byref? – Kiv

8

Jak wskazano w this question, unikając modyfikacji do NTP Linux wymaga CLOCK_MONOTONIC_RAW. Jest to zdefiniowane jako 4 w systemie Linux (od wersji 2.6.28).

Przenośne pobieranie poprawnej stałej #defined w nagłówku C z Pythona jest trudne; jest h2py, ale to naprawdę nie pomaga uzyskać wartości w czasie wykonywania.

+1

Uważam, że wybrana odpowiedź była niepoprawna i nie wyjaśniała skoki, zobacz [mój komentarz na ten temat] (http://stackoverflow.com/questions/3657289/linux-clock-gettimeclock-monotonic-strange-non-monotonic-behavior#comment12057005_3657385). Zarówno CLOCK_MONOTONIC, jak i CLOCK_MONOTONIC_RAW są monotoniczne, a jedyną różnicą jest to, że pierwsza poprawia prędkość zegara sprzętowego za pomocą NTP. – Tobu

23

Teraz w Pythonie 3.3 używałbyś time.monotonic.

+0

W CPython, zakładam, że to wewnętrznie używa 'CLOCK_MONOTONIC' i ** not **' CLOCK_MONOTONIC_RAW', z tym ostatnim nie będąc nawet dostępne w Pythonie 3.3. –

+0

@ABB: [moduł 'time' wie o" CLOCK_MONOTONIC_RAW "] (http://hg.python.org/cpython/file/e20f98a8ed71/Modules/timemodule.c#l1377) choć nie używa go tak daleko, jak Widze. Można [zdefiniować zegar, który używa go poprzez 'ctypes' nawet w Pythonie 2.7] (https://gist.github.com/zed/5073409) – jfs

+0

Jeśli czytam poprawnie dokumentację, wygląda na to, że w Pythonie 3.3 można uzyskać 'CLOCK_MONOTONIC_RAW' przez wywołanie' time.clock_gettime (time.CLOCK_MONOTONIC_RAW) ', co jest wspaniałe, więc gdy używasz go do mierzenia małych odstępów czasu, nigdy nie dostajesz błędu, gdy sieć aktualizuje czas za pomocą NTP (Network Time Protocol). Python time reference: https://docs.python.org/3/library/time.html#time.CLOCK_MONOTONIC_RAW. <- UWAGA: TYLKO DLA UNIX/LINUX. W przypadku Windows wystarczy wywołać 'time.clock()', która ma już mikrosekundę lub lepszą rozdzielczość, ponieważ używa QueryPerformanceCounter(). –

0

time.monotonic() może być przydatne:

zwraca wartość (w sekundach frakcyjną) z monotoniczny zegara, to znaczy zegara, którego nie można cofnąć. Zegar nie ma wpływu na aktualizacje zegara systemowego. Punkt odniesienia zwróconej wartości jest niezdefiniowany, więc ważna jest tylko różnica między wynikami kolejnych wywołań.

1

Oto jak uzyskać monotoniczny czas w Pythonie 2.7:

zainstalować pakiet monotonic:

pip install monotonic 

Następnie w Pythonie:

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.