O desempenho lento ocorre quando você copia dados para um servidor TCP usando um programa de API do Windows Sockets
Este artigo fornece soluções alternativas para o problema em que o desempenho lento ocorre quando você copia dados para um servidor TCP usando um programa de API do Windows Sockets.
Aplica-se a: Windows Server 2012 R2, Windows 10 - todas as edições
Número de KB original: 823764
Sintomas
Ao executar um programa que usa a API do Windows Sockets, você pode ter um desempenho lento ao copiar dados para um servidor TCP.
Se você fizer um rastreamento de rede com um farejador de rede, como o Microsoft Network Monitor, o servidor TCP enviará um segmento TCP ACK para o último segmento TCP em um fluxo de dados TCP no temporizador de reconhecimento atrasado (também conhecido como temporizador ACK atrasado). Por padrão, para sistemas operacionais Windows, o valor para esse temporizador é de 200 milissegundos (ms). Um fluxo de dados típico para o envio de 64 quilobytes (KB) de dados é semelhante à seguinte sequência:
Bytes do Client-Server> 1460
Bytes do Client-Server> 1460
ACK servidor-cliente>
Bytes do Client-Server> 1460
Bytes do Client-Server> 1460
ACK servidor-cliente>
....
Bytes do Client-Server> 1460
Bytes do Client-Server> 1460
ACK-PUSH servidor-cliente>
Bytes do Client-Server> 1296
-> ACK 200 ms atrasada
Motivo
Esse problema ocorre devido ao comportamento arquitetônico da API e do afd.sys do Windows Sockets. Esse problema ocorrerá se todas as seguintes condições forem verdadeiras:
O programa Soquetes do Windows usa soquetes que não bloqueiam.
Uma única chamada de envio ou chamada WSASend preenche todo o buffer de envio de soquete subjacente.
Por exemplo, o programa usa a função Soquetes
setsockopt
do Windows para alterar o buffer de envio de soquete padrão para 32 KB durante suas rotinas de inicialização de soquete:setsockopt( sock, SOL_SOCKET, 32768, (char *) &val, sizeof( int ));
Posteriormente, quando o programa envia dados, ele emite uma chamada de envio ou uma chamada WSASend e envia 64 KB de dados durante cada envio:
send(socket, pWrBuffer, 65536, 0);
Nesse cenário, sempre que o programa emite uma chamada de envio de 64 KB de dados, o programa retorna um código de erro SOCKET_ERROR se o buffer de soquete de 32 KB subjacente for preenchido. Depois de chamar a função WSAGetLastError, o programa recebe o código de erro WSAEWOULDBLOCK. A maioria dos programas usa a função selecionar Soquetes do Windows para marcar o status do soquete. Nesse cenário, a função select não relata o soquete como gravável até que o cliente receba o segmento TCP ACK pendente. Por padrão em um ambiente windows, isso pode levar até 200 ms devido ao algoritmo de reconhecimento atrasado.
O servidor TCP remoto reconhece todos os segmentos TCP antes que o cliente envie o último segmento TCP com o conjunto de bits push.
Solução alternativa
Para contornar esse problema, use qualquer um dos métodos a seguir.
Método 1: usar soquetes de bloqueio
Esse problema ocorre apenas com soquetes que não bloqueiam. Quando você usa um soquete de bloqueio, esse problema não ocorre porque afd.sys manipula o buffer do soquete de forma diferente. Para obter mais informações sobre como bloquear e não bloquear a programação do soquete, confira a documentação do SDK da Plataforma Microsoft.
Método 2: tornar o tamanho do buffer de envio do soquete maior que o tamanho do buffer de envio do programa
Para modificar o buffer de envio do soquete, use a função Soquetes getsockopt
do Windows para determinar o tamanho do buffer de envio do soquete atual (SO_SNDBUF) e use a setsockopt
função para definir o tamanho do buffer de envio do soquete. Quando você terminar, o valor SO_SNDBUF deve ser pelo menos 1 byte maior que o tamanho do buffer de envio do programa.
Modifique a chamada de envio ou a chamada WSASend para especificar um tamanho de buffer pelo menos 1 byte menor que o valor SO_SNDBUF. No exemplo anterior na seção "Causa" deste artigo, você pode modificar a chamada setsockopt para o valor a seguir,
setsockopt( sock, SOL_SOCKET, 65537, (char *) &val, sizeof( int ));
ou você pode modificar a chamada de envio para o seguinte valor:
send(socket, pWrBuffer, 32767, 0);
Você também pode usar qualquer combinação desses valores.
Método 3: modificar as configurações TCP/IP no servidor TCP
Importante
Esta seção, método ou tarefa contém etapas que descrevem como modificar o Registro. Entretanto, sérios problemas poderão ocorrer caso você modifique o Registro incorretamente. Portanto, siga essas etapas cuidadosamente. Para mais proteção, faça o backup do registro antes de modificá-lo. Em seguida, você poderá restaurar o registro se ocorrer um problema. Para obter mais informações sobre como fazer backup e restaurar o Registro, clique no número abaixo para ler o artigo na Base de Dados de Conhecimento Microsoft:
322756 Como fazer o backup e a restauração do Registro no Windows
Modifique as configurações TCP/IP no servidor TCP para reconhecer imediatamente os segmentos TCP de entrada. Essa solução alternativa funciona melhor em um ambiente que tem uma base de instalação de cliente grande e em que você não pode alterar o comportamento do programa. Para cenários em que o servidor TCP remoto é executado em um servidor baseado em Windows, você deve modificar o registro do servidor remoto. Para outros sistemas operacionais, consulte a documentação do sistema operacional para obter informações sobre como alterar o temporizador de reconhecimento atrasado.
Em um servidor que executa o Windows 2000, siga estas etapas:
- Iniciar Editor do Registro (Regedit.exe).
- Localize e clique na seguinte subchave do Registro:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
- No menu Editar , clique em Adicionar Valor e crie o seguinte valor de registro:
Nome do valor: TcpDelAckTicks
Tipo de dados: REG_DWORD
Dados de valor: 0 - Saia do Editor do Registro.
- Reinicie o Windows para que essa alteração entre em vigor.
Em um servidor que executa o Windows XP ou o Windows Server 2003, siga estas etapas:
- Inicie o Editor do Registro.
- Localize e clique na seguinte subchave do Registro:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
- No menu Editar, aponte para Novo e clique em Valor DWORD.
- Nomeie o novo valor TcpAckFrequency e atribua um valor de 1.
- Saia do Editor do Registro.
- Reinicie o Windows para que essa alteração entre em vigor.
Método 4: modificar o comportamento de buffer em afd.sys para soquetes não bloqueados
Importante
Esta seção, método ou tarefa contém etapas que descrevem como modificar o Registro. Entretanto, sérios problemas poderão ocorrer caso você modifique o Registro incorretamente. Portanto, siga essas etapas cuidadosamente. Para mais proteção, faça o backup do registro antes de modificá-lo. Em seguida, você poderá restaurar o registro se ocorrer um problema. Para obter mais informações sobre como fazer backup e restaurar o registro, clique no seguinte número de artigo para exibir o artigo na Base de Dados de Conhecimento da Microsoft: 322756 Como fazer backup e restaurar o registro no Windows
Observação
Essa chave de registro só está disponível para o Windows Server 2003 com o Service Pack 1 e os pacotes de serviço subsequentes.
- Clique em Iniciar, digite regedit.exee clique em OK.
- Localize e clique na seguinte subchave do Registro:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters
- No menu Editar, aponte para Novo e clique em Valor DWORD.
- Nomeie o novo valor NonBlockingSendSpecialBuffering e atribua um valor de 1.
- Sair do Registro Editor.
- Reinicie o Windows para que essa alteração entre em vigor.
Status
A Microsoft confirmou que este é um problema nos produtos Microsoft listados na seção "Aplicável a".
Referências
328890 Nova entrada de registro para controlar o comportamento de Reconhecimento TCP (ACK) no Windows XP e no Windows Server 2003
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de