2009-04-13 6 views
5

Oto skrypt Pythona, który ładuje url i rejestruje czas reakcji:Pierwsze TTFB (czas do pierwszego bajta) na żądanie HTTP

import urllib2 
import time 

opener = urllib2.build_opener() 
request = urllib2.Request('http://example.com') 

start = time.time() 
resp = opener.open(request) 
resp.read() 
ttlb = time.time() - start 

Ponieważ mój zegar jest owinięty wokół całego żądania/odpowiedzi (w tym lektury()), da mi to TTLB (czas do ostatniego bajtu).

Chciałbym również uzyskać TTFB (czas do pierwszego bajtu), ale nie jestem pewien, gdzie zacząć/zatrzymać mój czas. Czy urllib2 jest wystarczająco ziarnisty, aby dodać timery TTFB? Jeśli tak, to gdzie by poszli?

Odpowiedz

2

Przy użyciu obecnej pary open/read jest tylko jeden inny punkt czasowy - między nimi.

Wywołanie open() powinno być odpowiedzialne za faktyczne wysłanie żądania HTTP, i powinno (AFAIK) wrócić natychmiast po wysłaniu, gotowe do faktycznego odczytania przez aplikację odpowiedzi przez read().

Prawdopodobnie jest tak, że długa odpowiedź serwera spowodowałaby zablokowanie twojego zgłoszenia podczas połączenia z numerem read(), w którym to przypadku nie jest to TTFB.

Jednak jeśli ilość danych jest niewielka, tak i tak nie będzie dużej różnicy między TTFB i TTLB. W przypadku dużej ilości danych wystarczy zmierzyć, jak długo zajmuje read() zwrócenie pierwszej najmniejszej możliwej porcji.

+0

dzięki. robienie czegoś takiego jak "czas połączenia" dla otwartego kroku może przynieść mi to, czego potrzebuję (choć nie tak naprawdę TTFB) –

1

Domyślnie implementacja otwierania protokołu HTTP w urllib2 nie ma wywołań zwrotnych podczas wykonywania odczytu. Otwieracz OOTB dla protokołu HTTP to urllib2.HTTPHandler, który używa httplib.HTTPResponse do rzeczywistego odczytu przez gniazdo.

Teoretycznie można napisać własną podklasę HTTPResponse i HTTPHandler i zainstalować ją jako domyślny program do urllib2 przy użyciu install_opener. Byłoby to nietrywialne, ale nie straszliwe, więc jeśli zasadniczo skopiujesz i wkleisz bieżącą implementację HTTPResponse ze standardowej biblioteki i dostroisz tam metodę begin() w celu wykonania przetwarzania lub wywołania zwrotnego, gdy rozpocznie się odczytywanie z gniazda.

1

Aby uzyskać dobrą bliskość, należy wykonać odczyt (1). I pomieszaj czas.

Działa to całkiem dobrze dla mnie. Jedną z rzeczy, o której należy pamiętać: Python może ładować więcej niż jeden bajt na wywołanie read (1). W zależności od jego wewnętrznych buforów. Ale myślę, że większość narzędzi będzie zachowywać się tak samo niedokładnie.

import urllib2 
import time 

opener = urllib2.build_opener() 
request = urllib2.Request('http://example.com') 

start = time.time() 
resp = opener.open(request) 
# read one byte 
resp.read(1) 
ttfb = time.time() - start 
# read the rest 
resp.read() 
ttlb = time.time() - start 
5

należy użyć pycurl, nie urllib2

  1. zainstalować pyCurl:
    można używać pip/easy_install lub zainstalować go od źródła.

    easy_install pycurl

    może powinieneś być superuser.

  2. Wykorzystanie:

    import pycurl 
    import sys 
    import json 
    
    WEB_SITES = sys.argv[1] 
    
    def main(): 
        c = pycurl.Curl() 
        c.setopt(pycurl.URL, WEB_SITES)    #set url 
        c.setopt(pycurl.FOLLOWLOCATION, 1) 
        content = c.perform()      #execute 
        dns_time = c.getinfo(pycurl.NAMELOOKUP_TIME) #DNS time 
        conn_time = c.getinfo(pycurl.CONNECT_TIME) #TCP/IP 3-way handshaking time 
        starttransfer_time = c.getinfo(pycurl.STARTTRANSFER_TIME) #time-to-first-byte time 
        total_time = c.getinfo(pycurl.TOTAL_TIME) #last requst time 
        c.close() 
    
    data = json.dumps({'dns_time':dns_time,   
            'conn_time':conn_time,   
            'starttransfer_time':starttransfer_time,  
            'total_time':total_time}) 
    return data 
    

    jeśli nazwa == "główny":
    print main()