Corridas periódicas inexplicadas no uso da CPU do sistema no W2K3E

7

Temos um servidor Windows 2003 R2 Enterprise de 64 bits executando uma carga de trabalho personalizada que sofre de um problema de desempenho incomum. A versão reduzida abaixo sofre de uma corcunda menor, mas é qualitativamente a mesma.

Reduzimos para um aplicativo simples e simples que não faz nada além de:

  • ouvindo em um soquete
  • juntando-se a um grupo de multidifusão
  • ouvindo os pacotes chegando naquele grupo
  • lendo e descartando os pacotes

A própria aplicação de teste é uma versão ligeiramente modificada de Impulsione o receptor ASIO multicast exemplo, então não há realmente muito que deveria estar dando errado. Código real (!) Abaixo…

De vez em quando, durante a execução deste programa sob carga, a CPU desse processo aumentará com todo o processamento acontecendo no código do kernel:

(somenteaCPU6émostradaaqui.Duranteoteste(3h17m)todososoutrosprocessadoresestãoociosos)

Comovocêpodevernográfico,quandoospicosdecargaatingemtodootempodeprocessamentoestáacontecendonocódigodokernel.OtempogastoégastoprincipalmenteemChamadasdeProcedimentoAdiadas(nomáximo16,8%)enotratamentodeInterrupções(máx.8,5%).Parecequeháalgumtipodelimpezaadiadaacontecendo,masnãotemosideiadoquepoderiaser.

Atéondepodemosdizer,estáacontecendoapenasnoW2K3E-64.

Estáacontecendoemhardwarediferente(HS21,HS22,HS22V,HPDL380).

AexecuçãodoaplicativodetestenoWindows2008demonstraoproblemaemumaextensãomuitomenor(maisfrequentemente,mascomsaliênciasmenores).

Comopodemoscorrigirissoouondedevemosprocuraraseguir?

Códigorealdoexemplo:

voidhandle_receive_from(constboost::system::error_code&error,size_tbytes_recvd){if(!error){++m_receivedPackets;m_receivedBytes+=bytes_recvd;m_last64TotalBytes+=bytes_recvd;if((m_receivedPackets&0x3F)==0){printf("Received %u bytes in %u packets. The average size of the last 64 packets was %u bytes, and the last byte received was %x.\n", 
                m_receivedBytes, m_receivedPackets, m_last64TotalBytes / 64, m_buffer[ bytes_recvd - 1 ] );
            m_last64TotalBytes = 0;
        }

        m_socket.async_receive_from(
            boost::asio::buffer(m_buffer, max_length), m_senderEndpoint,
            boost::bind(&receiver::handle_receive_from, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }
    else
    {
        std::cerr << "An error occurred when performing an asyncronous read." << std::endl;
        m_socket.get_io_service().stop();
    }
}
    
por MikeyB 27.04.2012 / 23:34

3 respostas

1

"Parece que há algum tipo de limpeza adiada acontecendo, mas não temos ideia do que poderia ser."

Isso pode ser coleta de lixo, mas não tenho certeza se a coleta de lixo é exibida como tempo privilegiado. Se esta for uma aplicação .NET, você pode olhar para os contadores de desempenho .NET CLR Memory (Gen 2 em particular é caro).

Neste fim, adivinhar possíveis problemas parece um pouco para trás. Sua melhor aposta seria criar um perfil de seu aplicativo e ver o que ele está fazendo durante isso para ver quais são as chamadas que o aplicativo está fazendo. Você pode conseguir usar apenas o Process Monitor para assistir às syscalls.

    
por 28.04.2012 / 22:44
1

Eu assumo que o sistema está recebendo pacotes multicast. Você pode tentar impedir que ele receba os pacotes e veja se você vê o mesmo problema?

Que tal juntar-se ao grupo multicast, mas não ouvir os pacotes?

Você diz que isso está acontecendo em sistemas diferentes, mas e o hardware real da NIC? É possível que seja o mesmo nesses diferentes sistemas.

Atualização: Se todos os sistemas estiverem usando NICs Broadcom, é possível que o problema esteja na NIC. Em particular, os drivers Broadcom fornecidos pela Microsoft são péssimos; as do site da Broadcom são muito melhores.

    
por 06.05.2012 / 17:30
0

Você pode ver duas coisas: seu quantum thread e o que está causando seu DPC (chamadas de procedimento atrasadas).

O quantum de threads é muito fácil de ser endereçado (provavelmente um red-herring, mas pode também ser verificado);

  1. Clique com o botão direito em Meu computador
  2. Selecione as propriedades
  3. Selecione a guia Avançado
  4. Selecione "Configurações ..." em Desempenho
  5. Selecione a guia Avançado nas novas janelas (agora somos DOUBLE avançado!)
  6. Em Planejamento do Processador, que está selecionado? "Programas" ou "Serviços de segundo plano"?

Os Serviços em Segundo Plano mais prováveis estão selecionados, tente selecionar Programas. Isso diminuirá a quantidade de tempo entre as interrupções e permitirá que mais threads sejam executadas no mesmo período de tempo no processador. Você recebe mais interrupções, mas menos tempo de processamento.

As chamadas de procedimento atrasadas são um pouco mais difíceis de diagnosticar;

Como afirmado por @wfaulk, isso geralmente aponta para um problema de driver. Há uma ferramenta útil chamada DPC Latency Checker que ajudará você a diagnosticar esses problemas. Mesmo que isso esteja acontecendo em várias plataformas de hardware, todos eles ainda podem compartilhar um driver em comum. Execute o DPC Checker e siga as instruções em seu site.

Três perguntas de acompanhamento:

  1. Você está usando NICs agrupados? Eles usam a pilha TCP / IP para se comunicarem entre si e podem causar sérios problemas de DPC.

  2. Suas NICs suportam TCP Offload? Está habilitado?

  3. (Um tiro completo no escuro) O seu servidor de teste faz parte de um domínio? Os GPOs são atualizados a cada 90 minutos por padrão ...

por 09.05.2012 / 05:13