Я пытаюсь понять показатели производительности, которые я получаю, и как определить оптимальное количество потоков.
См. В нижней части этого поста для моих результатов
Я написал экспериментальный многопоточный веб-клиент на Perl, который загружает страницу, извлекает источник для каждого тега изображения и загружает изображение - отбрасывая данные.
Используется неблокирующее соединение с начальным тайм-аутом для каждого файла, равным 10 секундам, который удваивается после каждого тайм-аута и повторяется. Он также кэширует IP-адреса, поэтому каждый поток должен выполнить поиск DNS только один раз.
Общий объем загруженных данных составляет 2271122 байта в 1316 файлах через соединение 2,5 Мбит с http://hubblesite.org/gallery/album/entire/npp/all/hires/true/. Эскизы размещены компанией, которая утверждает, что специализируется на малой задержке для приложений с высокой пропускной способностью.
Время стен:
1 поток занимает 4:48 - 0 таймаутов
2 темы занимает 2:38 - 0 таймаутов
5 потоков занимает 2:22 - 20 таймаутов
10 потоков занимают 2:27 - 40 таймаутов
50 потоков занимают 2:27 - 170 таймаутов
В худшем случае (50 потоков) клиент использует менее 2 секунд процессорного времени.
средний размер файла 1.7k
среднее значение rt 100 мс (измеряется с помощью ping)
средняя скорость процессора / изображение 1 мс
Самая высокая средняя скорость загрузки составляет 5 потоков при общей скорости около 15 КБ / с.
Сервер действительно имеет довольно низкую задержку, поскольку для получения каждого изображения требуется всего 218 мс, а это означает, что в среднем сервер обрабатывает каждый запрос:
0 cli отправляет syn
50 ср.кв.син
50 срв отправляет syn + ack
100 кон конн / кл отправляет
150 srv recv's get
168 srv читает файл, отправляет данные, закрывает звонки
218 заголовков rec recv HTTP + полный файл в 2 сегмента MSS == 1448
Я вижу, что средняя скорость загрузки для каждого файла низкая из-за небольших размеров файлов и относительно высокой стоимости одного файла в настройке соединения.
Чего я не понимаю, так это того, почему я практически не вижу улучшения в производительности после двух потоков. Сервер кажется достаточно быстрым, но уже запускает тайм-аут соединений в 5 потоках.
Тайм-ауты, похоже, начинаются после примерно 900 - 1000 успешных подключений, будь то 5 или 50 потоков, что, я полагаю, является своего рода порогом регулирования на сервере, но я ожидаю, что 10 потоков все равно будут значительно быстрее, чем 2.
Я что-то здесь упускаю?
EDIT-1
Просто для сравнения я установил расширение DownThemAll Firefox и загрузил изображения, используя его. Я установил 4 одновременных соединения с 10-секундным таймаутом. DTM потребовалось около 3 минут, чтобы загрузить все файлы + записать их на диск, и он также начал испытывать таймауты после примерно 900 соединений.
Я собираюсь запустить tcpdump, чтобы попытаться получить лучшее представление о том, что происходит на уровне протокола tcp.
Я также очистил кэш Firefox и нажал перезагрузить. 40 секунд, чтобы перезагрузить страницу и все изображения. Это казалось слишком быстрым - может быть, Firefox держал их в кеше памяти, который не был очищен? Итак, я открыл Opera, и это также заняло около 40 секунд. Я предполагаю, что они намного быстрее, потому что они должны использовать конвейерную передачу HTTP / 1.1?
И ответ есть! ??
Так что после небольшого тестирования и написания кода для повторного использования сокетов с помощью конвейерной передачи я обнаружил некоторую интересную информацию.
При работе в 5 потоках нетранслируемая версия извлекает первые 1026 изображений за 77 секунд, но для извлечения оставшихся 290 изображений требуется еще 65 секунд. Это в значительной степени подтверждает теорию Мэтта о том, что мой клиент получил удар по событию SYN FLOOD
, в результате которого сервер перестал отвечать на мои попытки подключения в течение короткого периода времени. Тем не менее, это только часть проблемы, так как 77 секунд все еще очень медленно для 5 потоков, чтобы получить 1026 изображений; Если вы удалите проблему SYN FLOOD
, все файлы займут около 99 секунд. Поэтому, основываясь на небольшом исследовании и некоторых tcpdump
, кажется, что другая часть проблемы - это задержка и накладные расходы на установку соединения.
Здесь мы возвращаемся к вопросу поиска «сладкого пятна» или оптимального количества потоков. Я изменил клиент для реализации HTTP / 1.1 Pipelining и обнаружил, что оптимальное количество потоков в этом случае составляет от 15 до 20. Например:
1 поток занимает 2:37 - 0 таймаутов
2 потока занимает 1:22 - 0 таймаутов
5 потоков занимает 0:34 - 0 таймаутов
10 потоков занимают 0:20 - 0 таймаутов
11 потоков занимают 0:19 - 0 таймаутов
15 потоков занимают 0:16 - 0 таймаутов
Есть четыре фактора, которые
повлиять на это; задержка / RTT, максимальная сквозная пропускная способность, размер буфера recv
и размер загружаемых файлов изображений. Смотрите этот сайт для
обсуждение того, как размер буфера приема и задержка RTT влияют на доступность
ширина полосы .
В дополнение к вышесказанному, средний размер файла влияет на максимальный размер соединения
Скорость передачи. Каждый раз, когда вы отправляете запрос GET, вы создаете пустой пробел в
Ваш канал передачи, который является размером соединения RTT. Например, если
вы максимально возможная скорость передачи данных (размер буфера recv / RTT) составляет 2,5 Мбит и
ваш RTT составляет 100 мс, тогда каждый GET-запрос имеет минимальный разрыв в 32 КБ в вашем
труба. Для большого среднего размера изображения 320 кБ это составляет 10% накладных расходов
за файл, эффективно уменьшая доступную пропускную способность до 2,25 Мбит. Тем не мение,
для небольшого среднего размера файла 3,2 КБ накладные расходы увеличиваются до 1000% и
доступная пропускная способность уменьшается до 232 кбит / с - около 29 кБ.
Таким образом, чтобы найти оптимальное количество потоков:
Размер зазора = MPTR * RTT
MPTR / (размер MPTR / Gap + размер файла AVG) * размер файла AVG)
Для моего вышеописанного сценария это дает мне оптимальное количество потоков из 11 потоков, что очень близко к моим реальным результатам.
Если фактическая скорость соединения ниже теоретической MPTR, тогда
вместо этого следует использовать в расчете.