TCP, HTTP e o Sweet Spot Multi-Threading

Estou tentando entender os números de desempenho que estou recebendo e como determinar o número ideal de threads.

Veja no final deste post meus resultados

Eu escrevi um cliente web multi-threaded experimental em perl que baixa uma página, pega a fonte de cada tag de imagem e baixa a imagem - descartando os dados.

Ele usa uma conexão sem bloqueio com um tempo limite inicial por arquivo de 10 segundos, que dobra após cada tempo limite e tenta novamente. Ele também armazena em cache os endereços IP, para que cada thread precise fazer uma pesquisa de DNS apenas uma vez.

A quantidade total de dados baixados é de 2271122 bytes em 1316 arquivos via conexão de 2,5Mbit dehttp://hubblesite.org/gallery/album/entire/npp/all/hires/true/ . As imagens em miniatura são hospedadas por uma empresa que afirma se especializar em baixa latência para aplicativos de alta largura de banda.

Os tempos da parede são:

1 Tópico leva 4:48 - 0 timeouts
2 Threads leva 2:38 - 0 timeouts
5 Threads leva 2:22 - 20 timeouts
10 threads levam 2:27 - 40 timeouts
50 Threads levam 2:27 - 170 timeouts

Na pior das hipóteses (50 threads), menos de 2 segundos de tempo da CPU são consumidos pelo cliente.

tamanho médio do arquivo 1,7k
avg rtt 100 ms (conforme medido pelo ping)
média CPU cli / img 1 ms

A velocidade média mais rápida de download é de 5 threads, com cerca de 15 KB / s no geral.

Na verdade, o servidor parece ter uma latência bastante baixa, pois são necessários apenas 218 ms para obter cada imagem, o que significa que em média são necessários apenas 18 ms para o servidor processar cada solicitação:

0 cli envia syn
50 srv rcvs syn
50 srv envia syn + ack
100 cli conn estabelecido / cli envia get
150 srv recv's get
168 srv lê arquivo, envia dados, liga perto
218 cli recv HTTP cabeçalhos + arquivo completo em 2 segmentos MSS == 1448

Percebo que a velocidade média de download por arquivo é baixa devido aos tamanhos pequenos e ao custo relativamente alto por arquivo da configuração da conexão.

O que não entendo é por que não vejo praticamente nenhuma melhora no desempenho além de 2 threads. O servidor parece ser suficientemente rápido, mas já inicia o tempo limite das conexões em 5 threads.

Os tempos limite parecem iniciar após cerca de 900 - 1000 conexões bem-sucedidas, sejam 5 ou 50 threads, o que eu suponho que seja provavelmente algum tipo de limite de limitação no servidor, mas eu esperaria que 10 threads ainda fossem significativamente mais rápidos que 2.

Estou faltando alguma coisa aqui?

EDIT-1

Apenas para fins de comparação, instalei a extensão DownThemAll Firefox e baixei as imagens usando-a. Configurei para 4 conexões simultâneas com um tempo limite de 10 segundos. O DTM levou cerca de 3 minutos para baixar todos os arquivos + gravá-los no disco e também começou a sofrer tempos limite após cerca de 900 conexões.

Vou executar o tcpdump para tentar obter uma imagem melhor do que está acontecendo no nível do protocolo tcp.

Também limpei o cache do Firefox e carreguei em recarregar. 40 segundos para recarregar a página e todas as imagens. Isso pareceu rápido demais - talvez o Firefox os tenha mantido em um cache de memória que não foi limpo? Então eu abri o Opera e também levou cerca de 40 segundos. Suponho que eles sejam muito mais rápidos porque devem estar usando pipelining HTTP / 1.1?

E a resposta é! ??

Então, depois de um pouco mais de teste e gravação de código para reutilizar os soquetes via pipelining, descobri algumas informações interessantes.

Ao executar em 5 threads, a versão sem pipeline recupera as primeiras 1026 imagens em 77 segundos, mas leva mais 65 segundos para recuperar as 290 imagens restantes. Isso praticamente confirmaMattH's teoria sobre o meu cliente ser atropelado por umSYN FLOOD evento que faz com que o servidor pare de responder às minhas tentativas de conexão por um curto período de tempo. No entanto, isso é apenas parte do problema, pois 77 segundos ainda são muito lentos para 5 threads obterem 1026 imagens; se você remover oSYN FLOOD problema ainda levaria cerca de 99 segundos para recuperar todos os arquivos. Então, com base em um pouco de pesquisa e algunstcpdumpParece que a outra parte do problema é a latência e a sobrecarga da configuração da conexão.

Aqui é onde voltamos à questão de encontrar o "ponto ideal" ou o número ideal de threads. Modifiquei o cliente para implementar o pipelining HTTP / 1.1 e descobri que o número ideal de threads nesse caso é entre 15 e 20. Por exemplo:

1 Tópico leva 2:37 - 0 timeouts
2 Threads leva 1:22 - 0 timeouts
5 Threads leva 0:34 - 0 timeouts
10 Tópicos levam 0:20 - 0 timeouts
11 Tópicos tomam 0:19 - 0 timeouts
15 Tópicos tomam 0:16 - 0 timeouts

Existem quatro fatores que afetam isso; latência / rtt, largura de banda máxima de ponta a ponta, tamanho do buffer de recuperação e o tamanho dos arquivos de imagem que estão sendo baixados.Consulte este site para uma discussão sobre como o tamanho do buffer de recebimento e a latência RTT afetam a largura de banda disponível.

Além do acima, o tamanho médio do arquivo afeta a taxa máxima de transferência por conexão. Toda vez que você emite uma solicitação GET, cria uma lacuna vazia no seu tubo de transferência, que é o tamanho da conexão RTT. Por exemplo, se sua taxa de transferência máxima possível (tamanho do buffer de recv / RTT) é de 2,5 Mbit e seu RTT é de 100 ms, cada solicitação GET incorre em um espaço mínimo de 32 kB no seu canal. Para um tamanho médio de imagem grande de 320kB, que representa uma sobrecarga de 10% por arquivo, reduzindo efetivamente a largura de banda disponível para 2,25Mbit. No entanto, para um pequeno tamanho médio de arquivo de 3,2kB, a sobrecarga salta para 1000% e a largura de banda disponível é reduzida para 232 kbit / segundo - cerca de 29kB.

Então, para encontrar o número ideal de threads:

Tamanho da lacuna = MPTR * RTT
MPTR / (tamanho MPTR / Gap + tamanho do arquivo AVG) * tamanho do arquivo AVG)

Para o meu cenário acima, isso me fornece uma contagem ideal de 11 threads, o que é extremamente próximo dos meus resultados no mundo real.

Se a velocidade real da conexão for mais lenta que o MPTR teórico, ela deverá ser usada no cálculo.

questionAnswers(1)

yourAnswerToTheQuestion