Compartilhar via


Desempenho em drivers de rede

Minimizando o comprimento do caminho de envio e recebimento

Embora os caminhos de envio e recebimento diferem de driver para driver, há algumas regras gerais para otimizações de desempenho:

  • Otimize nos caminhos comuns. A ferramenta Kernprof.exe é fornecida com as compilações de desenvolvedor e IDW do Windows para extrair as informações necessárias. O desenvolvedor deve examinar as rotinas que consomem mais ciclos de CPU e tentar reduzir a frequência dessas rotinas sendo chamadas ou o tempo gasto nessas rotinas.

  • Reduza o tempo gasto no DPC para que o driver do adaptador de rede não use recursos excessivos do sistema, o que faria com que o desempenho geral do sistema sofresse.

  • Verifique se o código de depuração não foi compilado na versão final lançada do driver; isso evita a execução de código em excesso.

Particionando dados e código para minimizar o compartilhamento entre processadores

O particionamento é necessário para minimizar dados compartilhados e código entre processadores. O particionamento ajuda a reduzir a utilização do barramento do sistema e melhora a eficiência do cache do processador. Para minimizar o compartilhamento de recursos, os desenvolvedores de drivers devem considerar o seguinte:

  • Implemente o driver como um miniporto desserializado, conforme descrito em Drivers Desserializados de Miniporto NDIS.

  • Use estruturas de dados por processador para reduzir o acesso a dados globais e compartilhados. Isso permite que você mantenha contadores de estatística sem sincronização, o que reduz o comprimento do caminho do código e aumenta o desempenho. Para estatísticas vitais, existem contadores por processador que são somados em conjunto no momento da consulta. Se você precisar ter um contador global, use operações intertravadas em vez de bloqueios de rotação para manipular o contador. Consulte Usando mecanismos de bloqueio corretamente abaixo para obter informações sobre como evitar o uso de bloqueios de rotação.

    Para facilitar isso, KeGetCurrentProcessorNumberEx pode ser usado para determinar o processador atual. Para determinar o número de processadores ao alocar estruturas de dados por processador, KeQueryGroupAffinity pode ser usado.

    O número total de bits definido na máscara de afinidade indica o número de processadores ativos no sistema. Os drivers não devem assumir que todos os bits definidos na máscara serão contíguos porque os processadores podem não estar numerados consecutivamente nas versões futuras do sistema operacional. O número de processadores em um computador SMP é um valor baseado em zero.

    Se o driver mantiver dados por processador, você poderá usar a função KeQueryGroupAffinity para reduzir a contenção de linha de cache.

Evitando o compartilhamento falso

O compartilhamento falso ocorre quando os processadores solicitam variáveis compartilhadas independentes umas das outras. No entanto, como as variáveis estão na mesma linha de cache, elas são compartilhadas entre os processadores. Nessas situações, a linha de cache viajará entre processadores para cada acesso a qualquer uma das variáveis nela, causando um aumento nas liberações e recarregamentos de cache. Isso aumenta a utilização do barramento do sistema e reduz o desempenho geral do sistema.

Para evitar o compartilhamento falso, alinhe estruturas de dados importantes (como spin locks, cabeçalhos de fila de buffers, listas simplesmente encadeadas) aos limites de linha de cache usando NdisGetSharedDataAlignment.

Usando mecanismos de bloqueio corretamente

Os bloqueios de rotação podem reduzir o desempenho se não forem usados corretamente. Os drivers devem minimizar o uso de bloqueios de rotação usando operações intertravadas sempre que possível. No entanto, em alguns casos, um bloqueio de rotação pode ser a melhor opção para alguns fins. Por exemplo, se um driver adquire um bloqueio de rotação ao manipular a contagem de referência para o número de pacotes que não foram indicados de volta para o driver, não é necessário usar uma operação intertravada. Para obter mais informações, consulte Sincronização e Notificação em Drivers de Rede.

Aqui estão algumas dicas para usar mecanismos de bloqueio efetivamente:

Usando o DMA de 64 bits

DMA de 64 bits Se o adaptador de rede dá suporte a DMA de 64 bits, etapas devem ser tomadas para evitar cópias extras para endereços acima do intervalo de 4 GB. Quando o driver chama NdisMRegisterScatterGatherDma, a flag NDIS_SG_DMA_64_BIT_ADDRESS deve ser definida no parâmetro Flags.

Garantindo o alinhamento adequado do buffer

O alinhamento do buffer em um limite de linha de cache melhora o desempenho ao copiar dados de um buffer para outro. A maioria dos buffers de recebimento do adaptador de rede é alinhada corretamente quando são alocados pela primeira vez, mas os dados do usuário que eventualmente devem ser copiados para o buffer do aplicativo são desalinhados devido ao espaço de cabeçalho consumido. No caso de dados TCP (o cenário mais comum), o deslocamento devido aos cabeçalhos TCP, IP e Ethernet resulta em um deslocamento de 0x36 bytes. Para resolver esse problema, recomendamos que os drivers aloquem um buffer ligeiramente maior e insiram dados de pacote em um deslocamento de 0xA bytes. Isso garantirá que, após o deslocamento dos buffers em 0x36 bytes em relação ao cabeçalho, os dados do usuário serão alinhados corretamente. Para obter mais informações sobre limites de linha de cache, consulte a seção Comentários para NdisMAllocateSharedMemory.

Usando Scatter-Gather DMA

O DMA de Dispersão/Coleta de NDIS fornece suporte ao hardware para transferir dados para e de intervalos não contíguos de memória física. Scatter-Gather DMA usa uma estrutura SCATTER_GATHER_LIST , que inclui uma matriz de estruturas SCATTER_GATHER_ELEMENT e o número de elementos na matriz. Essa estrutura é recuperada do descritor de pacote passado para a função de envio do driver. Cada elemento da matriz fornece o comprimento e o endereço físico inicial de uma região de Scatter-Gather fisicamente contígua. O driver usa as informações de comprimento e endereço para transferir os dados.

Usar as rotinas de Scatter-Gather para operações de DMA pode melhorar a utilização de recursos do sistema, não bloqueando esses recursos estaticamente, como ocorreria se os registros de mapa fossem usados. Para obter mais informações, consulte NDIS Scatter/Gather DMA.

Se o adaptador de rede der suporte ao Descarregamento de Segmentação TCP (Descarregamento de Envio Grande), o driver precisará passar o tamanho máximo do buffer que pode obter de TCP/IP para o parâmetro MaximumPhysicalMapping dentro da função NdisMRegisterScatterGatherDma . Isso garantirá que o driver tenha registros de mapa suficientes para criar a lista de Scatter-Gather e eliminar quaisquer possíveis alocações e cópias de buffer. Para obter mais informações, consulte estes tópicos:

Suporte à restrição lateral de recebimento

Para minimizar interrupções durante a reprodução de mídia em aplicativos multimídia, os drivers NDIS 6.20 e posteriores devem dar suporte ao RST (Limite Lateral de Recebimento) no processamento de interrupções de recebimento. Para obter mais informações, consulte:

Restrição lateral de recebimento no NDIS 6.20 "Enviar e receber caminhos de código" em resumo das alterações necessárias para portar um driver de miniporto para o NDIS 6.20