Получение TTFB (время до первого байта) для HTTP-запроса - PullRequest
5 голосов
/ 13 апреля 2009

Вот скрипт на python, который загружает URL и фиксирует время отклика:

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

Поскольку мой таймер обернут вокруг всего запроса / ответа (включая read ()), это даст мне TTLB (время до последнего байта).

Я также хотел бы получить TTFB (время до первого байта), но я не уверен, где начать / остановить мою синхронизацию. Достаточно ли гранулирован urllib2 для добавления таймеров TTFB? Если так, куда они пойдут?

Ответы [ 4 ]

6 голосов
/ 12 августа 2016

вы должны использовать pycurl, а не urllib2

  1. установка pyCurl:
    Вы можете использовать pip / easy_install или установить его из исходного кода.

    easy_install pyCurl

    Может быть, вы должны быть суперпользователем.

  2. использование:

    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
    
    if __name__ == "__main__":    
        print main()
    
2 голосов
/ 13 апреля 2009

При использовании вашей текущей пары open / read возможна только одна другая временная точка - между двумя.

Вызов open() должен отвечать за фактическую отправку HTTP-запроса и должен (AFAIK) возвращаться, как только он будет отправлен, готовый к тому, что ваше приложение действительно прочитает ответ через read().

Технически это, вероятно, тот случай, когда длинный ответ сервера блокирует ваше приложение при вызове read(), и в этом случае это не TTFB.

Однако, если объем данных невелик, разница между TTFB и TTLB в любом случае не будет. Для большого объема данных просто измерьте, сколько времени потребуется read() для возврата первого наименьшего возможного фрагмента.

1 голос
/ 14 июня 2012

Чтобы получить хорошую близость, вы должны прочитать (1). И испортить время.

Это работает довольно хорошо для меня. Единственное, о чем вы должны помнить: при вызове read (1) python может загружать более одного байта. В зависимости от его внутренних буферов. Но я думаю, что большинство инструментов будут вести себя одинаково неточно.

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
1 голос
/ 13 апреля 2009

По умолчанию реализация открытия HTTP в urllib2 не имеет обратных вызовов при выполнении чтения. Средство открытия OOTB для протокола HTTP - urllib2.HTTPHandler, которое использует httplib.HTTPResponse для фактического чтения через сокет.

Теоретически, вы можете написать свои собственные подклассы HTTPResponse и HTTPHandler и установить его как средство открытия по умолчанию в urllib2, используя install_opener . Это было бы нетривиально, но не мучительно, так что если вы в основном копируете и вставляете текущую реализацию HTTPResponse из стандартной библиотеки и настраиваете там метод begin(), чтобы выполнить некоторую обработку или обратный вызов при начале чтения из сокета.

...