Почему многопоточная загрузка быстрее, чем однопотоковая?

13

На моем сервере есть один большой файл. Я считаю, что многопоточная загрузка может получить 20 Мбит, но одна нить может получить 10 Мбит, кто-нибудь может объяснить это?

Почему
источник
Несколько потоков, обслуживающих одно и то же TCP-соединение, или несколько потоков, каждый из которых имеет отдельные TCP-соединения? Также вы говорите, что сервер многопоточный, или клиент многопоточный, или оба?
Спифф

Ответы:

14

Обычно это происходит потому, что где-то между вами и другим сервером существует брандмауэр, ограничивающий каждый поток HTTP до 10 Мбит / с. Когда вы используете многопоточность, вы получаете 2x 10Mb (по одному для каждой нити).

Марк Хендерсон
источник
1
Я использую FTP, и на моем сервере нет ограничений
почему
@ почему: может быть, твой интернет-провайдер ограничивает каждое соединение до 10 Мбит / с? Можете ли вы получить больше, чем в тестере скорости?
Андре Парамес
4

Это связано с вашим пингом между вами и сервером и размером окна / размера окна tcpip, используемого вашей загружаемой программой.

По сути, если у вас 100 мс на сервер и вы запрашиваете пакеты размером 100 Кб, вы можете получать только 10 пакетов в секунду, используя 1 соединение, даже если ваша скорость интернета бесконечна.

BarsMonster
источник
Вам не нужно подтверждать каждый пакет, пока получатель очищает свой буфер с разумной скоростью, отправитель должен иметь возможность постоянно их перекачивать.
Андре Парамес
Это верно. Но даже с буфером 256 КБ, ping все еще вызывает значительное замедление
BarsMonster,
3

TCP работает лучше всего, когда вы «держите канал заполненным» - когда отправляющее приложение продолжает посылать буферы достаточно быстро, чтобы стек TCP отправителя постоянно получал данные, так что он всегда мог иметь данные «в полете» в сети, и когда получатель приложение продолжает читать из получающего TCP-стека достаточно быстро, чтобы окно TCP получателя никогда не заполнялось (опять же, поэтому отправляющий TCP-стек всегда может сохранять данные «в полете» в сети).

Я мог бы представить плохо написанное однопоточное приложение отправителя, которое передает один буфер в стек TCP, ждет, когда он полностью Acked, а затем передает другой буфер. Это означает, что как только конец первого буфера «в полете» в сети, отправляющему стеку TCP не хватает данных для отправки, что означает, что канал истощается и не заполняется до тех пор, пока не вернется Ack и приложение-отправитель. передает ему новый буфер.

Я мог бы также представить плохо написанное однопоточное приложение-получатель, которое недостаточно быстро читает из принимающего TCP-стека и, таким образом, позволяет заполнять буферы TCP-стека, что означает, что окно TCP заполняется, что приводит к тому, что отправляющий TCP-стек прекратить отправку, пока не откроется окно. Увеличение размера окна TCP получателя может немного помочь, но реальным решением в этом случае является более быстрое считывание данных.

Spiff
источник
Таким образом, это может не иметь ничего общего с однопоточностью?
Обезьяна
@ Ape-inago Конечно, хорошо написанное однопоточное приложение может поддерживать полный канал, да.
Spiff
2

Ну, это, вероятно, потому что вы можете передавать столько данных только через одно соединение. Однако в многопоточной программе вы можете иметь два соединения, которые получают данные одновременно и удваивают объем информации, которую вы можете получить. Есть некоторые ограничения в этом, например, скорость сервера, с которого вы скачиваете ... Снимаю шляпу у двух, кто написал многопоточный загрузчик, это нелегко написать.

Joshkunz
источник
1
Почему это так сложно? Вам просто нужно выделить отдельный раздел для каждого потока и позволить ему записать в соответствующий раздел файла результатов. Источник акселя кажется мне довольно простым.
Андре Парамес