2009-04-13 14 views
5

Aquí es un script en Python que carga una URL y captura el tiempo de respuesta:Conseguir TTFB (tiempo hasta primer byte) para una solicitud 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 

Desde mi temporizador se envuelve alrededor de la solicitud entera/respuesta (incluyendo lectura()), esto me dará el TTLB (tiempo hasta el último byte).

También me gustaría obtener el TTFB (tiempo hasta el primer byte), pero no estoy seguro por dónde empezar/detener mi sincronización. ¿Urllib2 es lo suficientemente granular como para agregar temporizadores TTFB? Si es así, ¿a dónde irían?

Respuesta

2

Usando su actual open/read par solo hay otro punto de sincronización posible - entre los dos.

La llamada open() debe ser responsable de enviar realmente la petición HTTP, y debe (que yo sepa) volver en cuanto que ha sido enviado, listo para su aplicación para leer realmente la respuesta a través read().

técnicamente es probablemente el caso de que una respuesta del servidor larga haría que su bloque de aplicación de la llamada a read(), en cuyo caso esto no es TTFB.

Sin embargo, si la cantidad de datos es pequeña, de todos modos no habrá mucha diferencia entre TTFB y TTLB. Para una gran cantidad de datos, simplemente mida cuánto tarda en read() devolver el primer fragmento más pequeño posible.

+0

gracias. hacer algo como "tiempo de conexión" para el paso abierto podría darme lo que necesito (aunque no realmente TTFB) –

1

De forma predeterminada, la implementación de la apertura de HTTP en urllib2 no tiene devoluciones cuando se realiza la lectura. El operador OOTB para el protocolo HTTP es urllib2.HTTPHandler, que usa httplib.HTTPResponse para realizar la lectura real a través de un socket.

En teoría, podría escribir sus propias subclases de HTTPResponse y HTTPHandler, e instalarlas como el abridor predeterminado en urllib2 usando install_opener. Esto no sería trivial, pero no insoportablemente, así que si básicamente copia y pega la implementación HTTPResponse actual de la biblioteca estándar y modifica el método begin() para realizar algún procesamiento o devolución de llamada cuando comienza la lectura desde el socket.

1

Para obtener una buena proximidad, debe leer (1). Y anote el tiempo.

Funciona bastante bien para mí. Lo único que debe tener en cuenta: python podría cargar más de un byte en la llamada de read (1). Dependiendo de sus búferes internos. Pero creo que la mayoría de las herramientas se comportarán igualmente inexactas.

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

se debe utilizar pycurl, no urllib2

  1. instalar pyCurl:
    puede utilizar PIP/easy_install, o instalar desde el código fuente.

    easy_install pycurl

    tal vez debería ser un superusuario.

  2. uso:

    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 
    

    si nombre == "principal":
    principal de impresión()