Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O Concurrency Visualizer ajuda os desenvolvedores a visualizar o comportamento de um aplicativo multiencadeado. Essa ferramenta inclui uma galeria de padrões comuns para aplicações multithreaded que têm comportamento inadequado. A galeria inclui padrões visuais típicos e reconhecíveis expostos por meio da ferramenta, juntamente com uma explicação do comportamento representado por cada padrão, o resultado provável desse comportamento e a abordagem mais comum para resolvê-lo.
Contenção de bloqueio e execução serializada
Às vezes, um aplicativo paralelizado continua a ser executado em série, embora tenha vários threads e o computador tenha um número suficiente de núcleos lógicos. O primeiro sintoma é um desempenho multithread ruim, talvez até um pouco mais lento do que uma implementação serial. No Modo de Exibição de Threads, você não vê vários threads em execução em paralelo; Em vez disso, você verá que apenas um thread está sendo executado a qualquer momento. Neste ponto, se você clicar em um segmento de sincronização em um thread, poderá ver uma pilha de chamadas para o thread bloqueado (pilha de chamadas de bloqueio) e o thread que removeu a condição de bloqueio (desbloqueio da pilha de chamadas). Além disso, se a pilha de chamadas de desbloqueio ocorrer no processo que você está analisando, um conector Thread-Ready será exibido. A partir desse ponto, você pode navegar até seu código a partir das pilhas de chamadas de bloqueio e desbloqueio para investigar ainda mais a causa da serialização.
Conforme mostrado na ilustração a seguir, o Concurrency Visualizer também pode expor esse sintoma na Visualização de Utilização da CPU, em que, apesar da presença de várias threads, o aplicativo consome apenas um núcleo lógico.
Para obter mais informações, consulte a seção "Começar pela seção do problema" no artigo Thread Performance - Perfil de simultaneidade de contenção de recursos no Visual Studio da MSDN Magazine.
Distribuição de carga de trabalho desigual
Quando uma distribuição irregular do trabalho ocorre em vários threads paralelos em um aplicativo, um padrão típico de etapa de escada é exibido à medida que cada thread conclui seu trabalho, conforme mostrado na ilustração anterior. O Visualizador de Concorrência geralmente mostra tempos de início muito próximos para cada thread. No entanto, esses threads normalmente terminam de maneira irregular em vez de terminar simultaneamente. Esse padrão indica uma distribuição irregular do trabalho entre um grupo de threads paralelos, o que pode levar à diminuição do desempenho. A melhor abordagem para esse problema é reavaliar o algoritmo pelo qual o trabalho foi dividido entre os threads paralelos.
Conforme mostrado na ilustração a seguir, o Visualizador de Concorrência também pode expor esse sintoma na Visualização de Utilização da CPU como uma redução gradual na utilização da CPU.
Excesso de assinatura
No caso de sobrescrição, o número de threads ativos em um processo é maior do que o número de núcleos lógicos disponíveis no sistema. A ilustração anterior mostra os resultados da sobrescrição, com uma preempção significativa em todos os threads ativos. Além disso, a legenda mostra uma grande porcentagem de tempo gasto em Preempção (84% neste exemplo). Isso pode indicar que o processo está solicitando que o sistema execute mais threads simultâneos do que o número de núcleos lógicos. No entanto, isso também pode indicar que outros processos no sistema estão usando recursos que foram considerados disponíveis para esse processo.
Você deve considerar o seguinte ao avaliar esse problema:
O sistema geral pode estar sobrecarregado. Considere que outros processos no sistema podem estar preemptando seus threads. Quando você pausa em um segmento de preempção no modo de exibição de threads, uma dica de ferramenta identificará o thread e o processo que preemptou o thread. Esse processo não é necessariamente o que foi executado durante todo o tempo em que seu processo foi preemptado, mas fornece uma dica sobre o que criou a pressão de preempção contra seu processo.
Avalie como o processo determina o número apropriado de threads para execução durante esta fase do trabalho. Se o processo calcular diretamente o número de threads paralelos ativos, considere modificar esse algoritmo para melhor considerar o número de núcleos lógicos disponíveis no sistema. Se você usar o Runtime de Simultaneidade, a Biblioteca Paralela de Tarefas ou PLINQ, essas bibliotecas executarão o trabalho de cálculo do número de threads.
E/S ineficiente
O uso excessivo ou uso indevido de E/S é uma causa comum de ineficiências em aplicativos. Considere a ilustração anterior. O Perfil da Linha do Tempo Visível mostra que 44% do tempo de thread visível é consumido pela E/S. A linha do tempo mostra grandes quantidades de E/S, o que indica que o aplicativo analisado é frequentemente bloqueado por E/S. Para ver detalhes sobre os tipos de E/S e onde seu programa está bloqueado, amplie as regiões problemáticas, examine o Perfil da Linha do Tempo Visível e clique em um bloco de E/S específico para ver as pilhas de chamadas atuais.
Bloquear comboios
Os comboios de travas ocorrem quando o aplicativo adquire travas em uma ordem por chegada e quando a taxa de chegada à trava é maior que a taxa de aquisição. A combinação dessas duas condições faz com que as solicitações para o bloqueio comecem a se acumular. Uma maneira de combater esse problema é usar bloqueios "injustos" ou bloqueios que dão acesso ao primeiro thread para encontrá-los em estados desbloqueados. A ilustração anterior mostra esse comportamento de comboio. Para resolver o problema, tente diminuir a disputa pelos objetos de sincronização e usar bloqueios injustos.