Pull to refresh

Comments 7

А зачем тут мультипроцессинг? Вы в цикле перебираете список серверов и последовательно запускаете новый процесс, ждете когда он завершится и потом запускаете следующий? Просто в цикле слишком скучно?


А зачем вообще тут pandas? Вы в курсе сколько оно весит? Ну не гигабайты, конечно, но, по сравнению с обычными пакетами — довольно большой. Вы выводите вообще одну строчку всего — почему вам не хватило, скажем, tabulate?


Вы, конечно, уже видели speedtest-cli, speedtest (он на Go) и даже устаревший pyspeedtest? Так, простите — зачем это?


UPD: ничего не настораживает вас вот в этом коде?


d = 0
try:
   ...
   d = (parent_conn.recv())
except:
   d[1] = d[2] = 0
С циклом разобрался, переписал функцию с использованием пула и параллельного map. Про pandas в статье указано, что для удобства вывода информации, я для себя еще импортирую sqlalchemy и записываю все в PSQL, но это уже вкусовщина, а tabulate никогда не использовал. Про speedtest-cli знаю и он работает только с id серверов, т.е url-ы не подкинуть, а в их списке серверов нет многих урлов нужных для замеров. Почти одноименное решение на Go не рассматривал(на PHP тоже такое есть, но тут опять же вкусовщина по поводу выбора языка и методов). Исключения тоже поправил. Скрипт писал для своих нужд, но почему бы не поделиться опытом, выслушать замечания и на их основе внести поправки. Спасибо за конструктив!
Я бы предпочёл немного другой вариант:
from timeit import default_timer as timer
import requests as r
start = timer()
r.get(r'https://speedtest.selectel.ru/10MB')
print('Download speed [mbits/s]:',round(80/(timer()-start)))

Впрочем, все эти скрипты не имеют никакого смысла без стандартизированной методики измерения и законодательно закреплённых норм. Сейчас скорость имеет лишь маркетинговый смысл в описании тарифа.

В дополнение к уже озвученной критике.


  1. Вы измеряете не скорость отдачи файла на сервер, а скорость отдачи файла на сервер плюс побочные действия, не связанные непосредственно с измерением требуемой скорости.
    Измерять временные интервалы необходимо непосредственно перед началом http-запроса и сразу по его окончанию.


  2. Измерять временные интервалы лучше при помощи time.monotonic().
    time() использует системные часы, которые могут быть изменены пользователем или системными службами, например, при автоматической корректировке часов при переходе на летнее или зимнее время соответствующего региона, на который настроена операционная система.
    monotonic() же лишён этого изъяна, связанного с переводом системных часов и всегда возвращает актуальное действительное значение больше предыдущего.



def upload(id, url):
    file_name = str(id) + 'random7000x7000.jpg'
    if os.path.exists(file_name):
        size = os.path.getsize(file_name)
        with open(file_name, 'r+b') as f:
            files = {'file': (file_name, f.read())}

        start = time.monotonic()
        r = requests.post(url, files=files)
        end = time.monotonic()

        if r.status_code == 200:
            duration = end - start
            sp = (((size * 8) / 1024) / 1024) / duration
            return sp
        else:
            print("Requests status code is '{}'".format(r.status_code), file=sys.stderr)
            return -1 
    else:
        print("No such file '{}'".format(file_name), file=sys.stderr)
        return -1 

Вот не лень вам было писать столько комментария на такую никчемную статью. Я тоже хотел эти моменты упомянуть, но поленился. Плюсанул вам в карму.


Вообще говоря, замер скорости — это тоже велосипед. Уже есть атрибут elapsed у Response объекта requests:


response = requests.post(url, data=post_fields, timeout=timeout)
print(response.elapsed.total_seconds())

Хотя бы одной причины для использования multiprocessing я так и не нашел.

Лениться вредно ;)
За карму спасибо!


И всё же есть разница между TTFB (elapsed содержит именно это значение) и собственно скоростью передачи данных по каналу.


Последнее обычно требует более изощрённых методов.
Обычно производят несколько (последовательных или параллельных) измерений полного времени передачи данных (то есть до последнего байта, как в примере автора) после чего вычисляют медиану полученных замеров, что впоследствии и подаётся, как реальная, практическая скорость передачи данных по каналу. Такой метод, к примеру, используется в iperf3. Такие замеры будут носить более объективных характер, так как могут сглаживать такие моменты, как Burst-технологии. Технология Burst предназначена для подачи увеличенной скорости при назначенном лимите на короткое время. Такие технологии широко используются в различных машрутизаторах, например, в Mikrotik.


Но даже в этом случае, реальная, практическая скорость передачи данных по каналу может быть необъективной и зависеть де-факто ещё и от прочих условий. Например, от типа данных (типа трафика). Скорость передачи определённых данных может регулироваться, например QoS.


Но если целью ставится измерение TTFB HTTP-запроса, то тогда лучше всё-таки так:


response.history[0].elapsed.total_seconds()

а то ж, можно и на 301 наткнуться и тогда де-факто, просто response.elapsed будет содержать значение, отличное от самого первого отклика от сервера, например, второе, после редиректа, то есть response.history[1].elapsed.


А вообще, измерять скорость канала данных лучше не через HTTP.


Суть TTFB
import datetime
import requests

n = datetime.datetime.now()
r = requests.get("https://habr.com", stream=False)
print(
    f"h\t:{r.history}\n"
    f"he\t:{r.history[0].elapsed.total_seconds()}\n"
    f"ce\t:{r.elapsed.total_seconds()}\n"
    f"fe\t:{(datetime.datetime.now()-n).total_seconds()}"
)
А вообще, измерять скорость канала данных лучше не через HTTP.

Ага, и поэтому в примере вы еще и https привели, чтобы добавить раундтрипы на handshake и на шифрацию? А вдобавок там наверняка gzip еще добавляется и какой размер в реальности пересылается — непонятно никому. Получили результат 42, но что с ним делать — непонятно.


Имело бы смысл открыть соединение и в течение, скажем, 20-30 секунд непрерывно слать поток случайных байт, а в конце считать сколько за известное время было отправлено. И да — лучше TCP или даже UDP, а мерять — на получателе в том числе сколько дошло.


А измеряется это все на реальном сервере с кучей еще параллельных задач и при не очень широком канале (а при широком зачем вообще мерять?) запустившийся процесс бэкапа, или репликации базы, или просто фоновая задача решила отправить 100500 писем — займет неизвестную часть канала и в результате вы получите неверные цифры, которые, опять же, применить непонятно к чему. То ли у провайдера провод на ветру качает, а может просто в соседнем здании народ ютуб смотрит.

Sign up to leave a comment.

Articles