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();
}
}