O NetBeans IDE 6.8 com o plug-in C/C++/Fortran apresenta a ferramenta Microestados da thread para observação dos estados de execução das threads. A ferramenta mostra uma visão geral da alteração de estados do tempo de execução das threads do seu projeto e uma visualização mais detalhada do estado individual das threads. Você pode detectar problemas no tempo de execução em seus aplicativos que podem não ser detectáveis ao depurar o código.
Este tutorial demonstra como usar a ferramenta Microestados da thread para projetos C/C++ em execução nos sistemas operacionais Solaris 10 ou OpenSolaris. A ferramenta é suportada somente em sistemas operacionais Solaris porque a tecnologia de contabilidade de microestado e o utilitário DTrace do Solaris são necessários para coletar os dados de estado da thread. A ferramenta Microestados da thread é executado por padrão quando o projeto NetBeans é executado nos sistemas operacionais Solaris.
Se estiver executando o IDE no Linux, Windows, ou MacOS X e tiver um sistema Solaris disponível na sua rede, você pode configurar seu projeto para usar o sistema Solaris como uma máquina de desenvolvimento remoto. O desenvolvimento remoto permite que você use a ferramenta de criação de perfil Microestados da thread e outras ferramentas baseadas no Solaris mesmo quando o IDE é executado em Linux, Windows ou MacOS X. Consulte o Tutorial de desenvolvimento remoto C/C++ para obter mais informações sobre como configurar para construir uma máquina de desenvolvimento remoto.
Este tutorial usa um projeto em execução em um sistema Solaris baseado no processador SPARC. Você pode seguir as etapas do tutorial se estiver executando o NetBeans IDE 6.8 no Solaris ou OpenSolaris em sistemas baseados em SPARC ou x86. Observe que este tutorial usa "sistemas operacionais Solaris" para se referir tanto ao sistema operacional OpenSolaris quanto ao Solaris 10.
Contabilidade de microestado do Solaris
Muitos sistemas operacionais coletam as estatísticas da CPU a cada ciclo de clock da CPU ou em um intervalo de tempo fixo. Os sistemas operacionais Solaris usam uma tecnologia denominada contabilidade de microestado para coletar as estatísticas da CPU e das threads, em cada evento. Todas as atividades da thread são rastreadas e o sistema registra o momento em que cada thread passa de um estado de execução a outro. Estes carimbos de data/hora permitem ver quando tempo uma thread gasta em execução, estado de repouso, espera, bloqueada, etc. A técnica permite que estatísticas muito precisas sejam coletadas sem aumentar significativamente a sobrecarga do sistema.
Para obter mais informações sobre a contabilidade de microestado, consulte o blog informativo do engenheiro da Sun Eric Schrock sobre Contabilidade de microstado no Solaris 10.
Configurando seu ambiente Solaris para o tutorial
Para poder usar a ferramenta Microestados da thread, a conta de usuário do Solaris usada ao executar o NetBeans deve ter privilégios suficientes do DTrace para observar o comportamento do sistema. A conta de usuário deve ter os privilégios dtrace_user, dtrace_proc e dtrace_kernel.
Se estiver executando seu projeto em uma máquina de desenvolvimento remoto Solaris, os privilégios do DTrace deve estar definidos na sua conta de usuário na máquina remota.
Para verificar os seus privilégios do DTrace, digite o seguinte no prompt de comando: /bin/ppriv $$
Se sua conta tiver os privilégios necessários, o comando ppriv deve retornar algo semelhante a:
E: basic,dtrace_kernel,dtrace_proc,dtrace_user
I: basic,dtrace_kernel,dtrace_proc,dtrace_user
P: basic,dtrace_kernel,dtrace_proc,dtrace_user
L: all
A linha que começa com "I:" é importante porque especifica os privilégios herdados pelos programas iniciados a partir do seu shell. Se a sua conta não tiver os privilégios herdados necessários, e se você não tiver privilégios de administrador ou de acesso raiz ao seu sistema, você deve pedir ao seu administrador de sistema que adicione os privilégios herdáveis dtrace_user, dtrace_proc e dtrace_kernel a sua conta.
Se tiver privilégios de administrador ou acesso raiz ao seu sistema, você pode conceder os privilégios necessários a sua conta de usuário conforme descrito abaixo.
Para conceder permanentemente os privilégios necessários do DTrace a uma conta de usuário:
Certifique-se de que a conta de usuário cujos privilégios você deseja modificar esteja desconectada do sistema.
Efetue logon como superusuário (raiz) ou como outro usuário administrador.
Digite o seguinte no prompt de comando e substitua username pelo nome da conta de usuário que está sendo modificada:
$ usermod -K defaultpriv=basic,dtrace_kernel,dtrace_user,dtrace_proc username
A seguir, você pode efetuar logon na conta de usuário, iniciar o NetBeans IDE e usar as ferramentas de criação de perfil com o provedor de dados DTrace.
Para conceder temporariamente os privilégios necessários do DTrace a uma conta de usuário:
Digite o seguinte para determinar o ID de processo do shell:
$ echo $$
Torne-se superusuário (raiz) ou outro usuário administrador.
Digite o seguinte e substitua process-ID pelo ID do processo que o comando echo retornou:
$ ppriv -s I+dtrace_user,dtrace_proc,dtrace_kernelprocess-ID
Todos os comandos digitados no shell especificados pelo process-ID agora herdam os privilégios necessários. A conta de usuário pode iniciar o NetBeans IDE neste shell e usar a ferramenta de criação de perfil Microestados da thread.
Criar o projeto para o tutorial
Para explorar os recursos de perfilamento do microestado da thread, criaremos um projeto a partir do aplicativo de amostra ProfilingDemo que está incluído no IDE.
O aplicativo ProfilingDemo apresenta três estágios nos quais realiza duas tarefas repetidamente durante 10 segundos, usando três técnicas diferentes para gerar algumas atividades interessantes para serem mostradas nas ferramentas de criação de perfil. A primeira tarefa é gravar alguns dados em um arquivo e a segunda tarefa realiza alguns cálculos. Cada conjunto de duas tarefas é realizado um número de vezes igual ao número de CPUs detectado na máquina de desenvolvimento. Em um sistema com um único processador, o programa realiza as duas tarefas uma vez. Em uma máquina de desenvolvimento com 32 núcleos, o programa realiza as duas tarefas 32 vezes. É necessário pressionar a tecla Enter para iniciar cada conjunto de tarefas, portanto é preciso estar atento.
Os estágios do ProfilingDemo são os seguintes:
Sequential Demo possui uma única thread e executa as dois tarefas, uma depois da outra, cada uma durante 10 segundos. Isso pode demorar algum tempo em um sistema com um grande número de CPUs porque mais conjuntos de tarefas são realizados, um após o outro.
Parallel Demo possui várias threads e realiza as mesmas tarefas de gravação no arquivo e cálculos simultaneamente em threads diferentes, uma vez em cada CPU. Este estágio é muito mais rápido do que na Sequential Demo em máquinas com vários núcleos porque, na Sequencial Demo, embora se realize o mesmo número de tarefas, tais tarefas são executadas simultaneamente. No entanto, as threads podem acessar os mesmos dados de forma competitiva, o que pode levar à obtenção de resultados imprecisos.
Pthread Mutex Demo também possui várias threads e realiza as mesmas tarefas de gravação e cálculos que os outros estágios de demonstração. No entanto, o código usa bloqueios de exclusão mútuos para evitar que várias threads acessem conjuntamente determinadas funções.
Para criar o projeto ProfilingDemo
Abra o assistente para Novo projeto em Arquivo > Novo projeto.
No assistente, selecione a categoria Amostras e, a seguir, selecione a subcategoria C/C++.
Selecione a amostra Profiling Demo como mostrado na figura e clique em Avançar.
Você pode escolher o nome do projeto e a localização do projeto. Utilizamos o ProfilingDemo_1 padrão em nosso diretório NetBeansProjects.
Clique em Terminar para sair do assistente e criar o projeto.
Configurar as propriedades do projeto
Clique com o botão direito do mouse no nó do projeto ProfilingDemo_1 na aba Projetos e selecione Propriedades.
Selecione o nó Construir no painel Categorias.
Selecione SunStudio_12 como a coleção de ferramentas e clique em Aplicar.
Também é possível usar a coleção de ferramentas GNU porque a ferramenta Microestados da thread não depende das ferramentas Sun Studio.
Selecione o nó Executar no painel Categorias. No Tipo de console, selecione Janela de saída e clique em Aplicar. Isso permite que você veja a saída do programa na Janela de saída do IDE em vez de em uma janela de terminal externa, conforme mostrado neste tutorial.
Selecione o nó Perfil no painel Categorias. Selecione Mostrar indicadores de criação de perfil durante a execução.
Na Configuração de perfil, selecione C/C++ DTrace Extended.
Clique em OK na caixa de diálogo Propriedades do projeto.
Construir e executar o projeto ProfilingDemo
Clique com o botão direito do mouse no nó do projeto Profiling Demo e selecione Construir.
A aba Saída mostra os resultados da construção similar aos abaixo mostrados. Os avisos sobre argumentos não compatíveis, caso sejam exibidos, podem ser ignorados.
Clique com o botão direito do mouse no nó do projeto Profiling Demo e selecione Executar.
Pressione Enter sempre que for solicitado durante a execução do projeto ProfilingDemo. A saída é semelhante à captura de tela abaixo.
A aba Monitor de execução é aberta para exibir os gráficos dinâmicos da ferramenta Microestados da thread e de todas as outras ferramentas especificadas na configuração de perfil C/C++ DTrace Extended.
Na captura de tela seguinte, todas as ferramentas são exibidas com a ferramenta Microestados da thread realçada em vermelho.
Se quiser ver todas as ferramentas, pode ser necessário aumentar o tamanho da aba Monitor de execução clicando e arrastando para cima a borda superior da aba Monitor de execução. Também é possível arrastar o lado direito para ampliá-las.
Observe que a janela de saída do programa ProfilingDemo mostra o que ele está fazendo para que você possa comparar com os dados que o IDE está representando graficamente nas ferramentas. Por exemplo, o programa exibe a quantidade de memória que está alocando, realiza cálculos e, a seguir, libera a memória. Você pode ver os gráficos refletindo a atividade do programa.
Explorar os microestados da thread
O gráfico de Microestados da thread na janela Monitor de execução mostra uma visão geral das threads do programa à medida que passam por vários estados de execução durante a execução do projeto. O recurso de contabilidade de microestado do Solaris usa o utilitário DTrace para proporcionar informações minuciosas sobre o estado de cada thread conforme ela entra e sai de dez diferentes estados de execução.
A ferramenta Microestados da thread mostra graficamente informações de estado resumidas de todas as threads criadas durante a execução do projeto. São mostrados somente quatro estados: repouso, espera, bloqueado e execução. Estes estados apresentam uma visualização simplificada ou resumida de dez possíveis microestados e oferece uma visão geral dos estados de todas as threads em execução no seu programa. Por exemplo, o tempo gasto no estado Execução representa todos os tipos estados: execução no modo de usuário, execução nas chamadas do sistema, execução nas falhas de página, execução nas capturas.
A captura de tela abaixo foi obtida no início da execução do programa, durante a parte SEQUENTIAL DEMO, na qual as duas tarefas são executadas uma depois da outra em uma única thread. Os pontos nos quais a thread está em repouso corresponde aos pontos nos quais o programa esta esperando que você pressione Enter.
Na parte inferior da janela Monitor de execução, observe que há uma barras de rolagem. Clique e arraste-a para a esquerda e para a direita para que possa ver os dados em todas as ferramentas de criação de perfil, do início ao fim da execução.
Na captura de tela abaixo em aproximadamente 0:42 segundos, observe que o número de threads mostrado em Microestados da thread aumenta para três conforme o programa entra na parte da PARALLEL DEMO. A thread principal inicia duas threads adicionais para executar duas tarefas em paralelo, cada uma em sua própria thread. Você pode ver que é gasto muito tempo no estado Espera (amarelo) e no estado Repouso (azul), e menos tempo no estado Execução (verde). Nenhum período de tempo é gasto no estado Bloqueado (laranja) durante a parte da PARALLEL DEMO porque esta parte do programa não implementa nenhuma tática de sincronização da thread, como os bloqueios de mutex que podem bloquear threads.
Na captura de tela abaixo em aproximadamente 0:56 segundos, observe que o estado Bloqueado mostrado em laranja aparece pela primeira vez durante a execução do programa. Corresponde ao ponto no qual o programa entra na parte da PTHREAD MUTEX DEMO, na qual cada thread usa bloqueios de exclusão mútuos para evitar que outras interfiram em determinados pontos. Cada thread pode ser executada de forma ativa somente após obter o bloqueio de mutex. Uma thread é bloqueada ao tentar acessar uma seção de código bloqueada quando outra thread possui um bloqueio de mutex. O uso de bloqueios de exclusão mútuos evita que as threads entrem em disputa (race condition) pelos dados, quando as threads têm acesso simultâneo aos mesmos dados.
Clique no botão Detalhes da thread para exibir detalhes sobre os microestados da thread.
A aba Detalhes da thread é aberta para exibir uma representação gráfica da linha do tempo de todas as threads em execução no programa, juntamente com informações detalhadas de estado.
Detalhes da thread mostra as transições de estado de cada thread durante todo o tempo de execução do programa. Vamos explorar um pouco esta janela para ver o que é possível fazer.
Mova (mas não clique) o ponteiro do mouse sobre uma das áreas coloridas de uma thread e você verá um pop-up que exibe detalhes sobre o que está acontecendo neste momento em particular. Os detalhes exibidos correspondem ao tempo no qual os dados foram coletados e a porcentagem de tempo gasto em cada estado da thread em tal momento. Ao mover o ponteiro do mouse sobre a área "Resumo" à direita, o pop-up exibe as porcentagens da execução completa da thread.
Você pode controlar o que é mostrado na janela Detalhes da thread alterando várias configurações:
Clique em Nível de detalhe para selecionar o nível de detalhe das informações que deseja ver. As opções são Básico, Moderado ou Avançado, em que a visualização mais simples exibe apenas quatro estados de execução generalizados e a mais complexa exibe dez microestados.
Clique na lista Exibir e selecione que tipo de threads exibir. A opção Somente threads concluídas mostra apenas as threads que foram concluídas durante a execução do programa. A opção Somente threads ativas mostra apenas as que não foram concluídas. A opção Todas as threads mostra tanto as threads concluídas quanto as threads ativas.
Clique em uma thread individual e observe que a thread está realçada. A seguir, pressione a tecla Shift e clique em outra thread para selecionar uma série de threads. Também é possível selecionar várias threads que não estão juntas pressionando a tecla Control antes de clicar nas threads que deseja selecionar. Quando as threads desejadas estão realçadas, clique com o botão direito do mouse e selecione Mostrar somente threads selecionadas. Você pode ver todas as threads novamente usando a lista Exibir.
Clique com o botão direito do mouse em uma thread e selecione Nome da thread para alterar o nome padrão "Thread n" pelo nome das funções que são executadas pelas threads.
É possível aumentar o zoom dos gráficos da thread para ter uma visão mais detalhada e ver mais dados de microestado clicando no botão com sinal de adição (+) na parte superior esquerda da janela Detalhes da thread. Também é possível diminuir o zoom para ter uma visão mais abrangente clicando no botão com sinal de subtração (-). O botão Mostrar execução completa mostra os dados de toda a execução do projeto na janela Detalhes da thread sem ter que efetuar rolagem. Clique outra vez no botão para voltar à visualização dos detalhes da thread com barra de rolagem.
Na captura de tela abaixo, vemos a janela Detalhes da thread com zoom. Os IDs da thread são funções básicas da thread e o Nível de detalhe está definido como Avançado.
Clique em um determinado ponto na janela Detalhes da thread e uma nova aba Pilha de chamada da thread é exibida abaixo para mostrar um despejo de pilha. Na exibição do despejo de pilha, é possível expandir nós individuais da pilha para ver as chamadas, ou clicar com o botão direito do mouse no nó superior e selecione Expandir todos para ver todas as chamadas que estão ocorrendo neste exato momento.
Na captura de tela abaixo, clicamos na Thread 5 em aproximadamente 1:03 perto do fim da execução.
Clique duas vezes em uma função que não seja de cor cinza, como mutex_threadfunc na tela abaixo, para abrir o arquivo de código-fonte onde a função é chamada.
Clique novamente em uma thread na janela Detalhes da thread. Você pode navegar pela linha do tempo da thread usando o mouse ou o teclado.
Com o mouse, clique com o botão direito do mouse e selecione Navegarte > Mover cursor para a esquerda move o foco para a esquerda na thread atualmente selecionada. Também é possível definir um ponto na linha do tempo selecionando Navegar > Definir cursor, o que atualizará o conteúdo da Pilha de chamada da thread. Você pode alterar o foco para a Pilha de chamada da thread selecionando Navegar > Ir para a visualização da pilha.
Para usar os atalhos do teclado para navegar na linha do tempo da thread na janela Detalhes da thread, pressione as seguintes teclas:
Ctrl+seta esquerda e Ctrl+seta direita para rolar para a esquerda e para a direita na linha do tempo da thread.
Ctrl+seta para baixo para selecionar um ponto na linha do tempo, o que atualizará a Pilha de chamada da thread de tal ponto.
Alt+seta para baixo para destacar a entrada na janela Pilha de chamada da thread.
Na janela Pilha de chamada da thread, você pode usar as teclas de setas e Enter para abrir os arquivos de código-fonte associados às funções.
Definições de estado da thread
Os microestados da thread do Solaris, mostrados no nível de detalhe Avançado, são descritos abaixo.
Estado
Descrição
Usuário em execução
O percentual de tempo que o processo gastou no modo de usuário.
Sistema em execução
O percentual de tempo que o processo gastou no modo de sistema.
Outros em execução
O percentual de tempo que o processo gastou em processar capturas do sistema, etc.
Falha da página de texto
O percentual de tempo que o processo gastou em processar falhas de páginas de texto.
Falha da página de dados
O percentual de tempo que o processo gastou em processar falhas de páginas de dados.
Bloqueado
O percentual de tempo que o processo gastou esperando os bloqueios do usuário.
Repouso
O percentual de tempo que o processo gastou no estado de repouso.
Espera
O percentual de tempo que o processo gastou esperando a CPU.
Veja também
Para obter mais informações sobre a tecnologia DTrace usada em segundo plano para compilar dados do projeto em execução, consulte o Portal BigAdmin DTrace.
Este tutorial demonstrou os seguintes pontos sobre a ferramenta de criação de perfil Microestados da thread:
As informações de microestado da thread são coletadas automaticamente nas plataformas Solaris com o utilitário DTrace do Solaris.
Os indicadores gráficos da criação de perfil exibidos podem ser selecionados através das Configurações do perfil.
A ferramenta Microestados da thread pode ser encontrada somente na configuração de perfil C/C++ DTrace Extended ou na sua própria configuração.
As configurações de perfilamento estão localizadas nas propriedades do projeto na categoria Perfil.
Ao clicar no botão Detalhes da thread, são exibidas as informações detalhadas do estado das threads individuais.
Ao clicar nas threads na aba Detalhes da thread, é exibido o despejo de pilha de todas as threads em execução no ponto selecionado.
Ao clicar nas funções no despejo de pilha da thread, o arquivo de código-fonte associado é aberto no Editor.
Se tiver acesso a um sistema que executa um sistema operacional Solaris em sua rede, você poderá utilizar a ferramenta Microestados da thread a partir da sua máquina Windows ou Mac ao configurar o sistema Solaris como um host de desenvolvimento remoto para construir e executar seus projetos.