CPU de monitoramento de desempenho do Linux

CPU de monitoramento de desempenho do Linux

1. Introdução à CPU

O escalonador do kernel será responsável por escalonar dois tipos de recursos: threads (únicas ou múltiplas) e interrupções .
O agendador define diferentes prioridades para diferentes recursos.

Prioridade: Interrupções (interrupção) > Processos do Kernel (Sistema) (processamento do kernel/processo do sistema) > Processos do Usuário (processo do usuário)

**Interrupções (interrupção)**: O dispositivo notifica o kernel que concluiu um processo de processamento de dados. Por exemplo, quando um dispositivo de placa de rede entrega pacotes de rede ou uma peça de hardware fornece uma solicitação de E/S.

Processos do Kernel (Sistema) : Todos os processos do kernel controlam a prioridade.

Processos do usuário : todos os programas de software são executados no espaço do usuário. Este bloco tem baixa prioridade no mecanismo de escalonamento do kernel.

Nós nos concentramos nas seguintes 3 partes da CPU:

  • utilização
  • contexto (troca de contexto)
  • executar filas

2. Utilização da CPU

A utilização da CPU é definida como uma porcentagem do uso da CPU e depende principalmente de quais recursos estão tentando acessar a CPU. Uma das métricas mais importantes para avaliar um sistema é observar a utilização da CPU. Para alcançar o mais alto desempenho ou escalabilidade de um aplicativo, ele deve aproveitar ao máximo os ciclos de CPU alocados a ele, sem desperdiçá-los.

Um aplicativo consumindo muita CPU não significa que o desempenho ou a escalabilidade estejam no máximo. Para descobrir como um aplicativo usa os ciclos de CPU, você precisa monitorar o uso da CPU do sistema. Se uma CPU for totalmente utilizada, a proporção equilibrada entre as categorias de utilização deverá ser:

  • 65% - 70% do tempo do usuário
  • 30% - 35% do tempo do sistema
  • 0% - 5% de tempo ocioso

A utilização da CPU é classificada da seguinte forma:

Tempo do usuário (tempo de processo do usuário) : Sobre a porcentagem de tempo de sobrecarga da CPU do processo executado no espaço do usuário.

O uso da CPU no modo de usuário refere-se à porcentagem de tempo gasto na execução do código do aplicativo como uma porcentagem do tempo total da CPU.

Tempo do Sistema (thread do kernel e tempo de interrupção): Referente à porcentagem de tempo de sobrecarga da CPU para threads e interrupções no espaço do kernel.

O uso da CPU no estado do sistema refere-se à porcentagem de tempo que o aplicativo executa chamadas do sistema operacional em relação ao tempo total da CPU.

O alto uso da CPU no estado do sistema significa que há competição por recursos compartilhados ou muita interação entre dispositivos de E/S.
Idealmente, quando um aplicativo atinge desempenho e escalabilidade máximos, o uso da CPU do sistema é de 0%. Portanto, é necessário reduzir ao máximo o uso da CPU do sistema.

Wait IO (tempo de espera da solicitação de IO): a porcentagem de tempo ocioso de sobrecarga da CPU em que todos os threads do processo são bloqueados aguardando a conclusão de uma solicitação de IO.

Ocioso: a porcentagem de tempo que um processo em estado ocioso completo gasta no processador da CPU.

3. Monitore a CPU

3.1. Use top para monitorar o uso da CPU

Insira a descrição da imagem aqui

A metade superior são as informações estatísticas de todo o sistema, e a metade inferior são as informações estatísticas de cada processo. Por padrão, elas são organizadas de alto a baixo de acordo com o uso da CPU.

3.2. Use vmstat para monitorar o uso da CPU

Insira a descrição da imagem aqui

contente ilustrar
nós Uso de CPU no modo de usuário
e Estado do sistema (kernel e interrupção) Uso da CPU
eu ia Taxa de inatividade ou taxa de disponibilidade de CPU
de Porcentagem de todos os threads executáveis ​​bloqueados aguardando solicitações de E/S

nós+sy+id=100

3.3. Use mpstat para monitorar o uso da CPU

O kernel do Linux trata um processador dual-core como tendo 2 CPUs, portanto, um processador dual-core com dois núcleos reportará que 4 CPUs estão disponíveis.

O valor estatístico da utilização da CPU fornecido pelo comando mpstat é aproximadamente o mesmo do vmstat, mas o mpstat pode monitorar o uso da CPU de cada processador virtual , o que ajuda a descobrir que alguns threads no aplicativo consomem mais ciclos de CPU do que outros threads. Ou todos os threads do aplicativo basicamente compartilham os ciclos da CPU igualmente. Se for o último, significa que a escalabilidade da aplicação é melhor.

Se o intervalo de relatório mpstat não for especificado, será gerada a soma de todos os dados mpstat desde a última inicialização do sistema.

Insira a descrição da imagem aqui

contente ilustrar
usr Porcentagem de tempo de CPU gasto na execução do código do usuário
sistema Porcentagem de tempo de CPU gasto na execução do código do kernel
ioespere Indica o tempo de espera de IO
parado Representa a porcentagem de tempo ocioso da CPU

Use mpstat para monitorar o uso da CPU de cada processador virtual:

Insira a descrição da imagem aqui

-P 0 significa especificar a visualização do uso da primeira CPU (o subscrito começa em 0)

3.4. Use pidstat para monitorar o uso individual da CPU

Exemplo: aumente o uso da CPU executando o script WhileTrue.py e visualize o uso da CPU do processo. Comando: pidstat -u 1 -p 3336

Insira a descrição da imagem aqui

Insira a descrição da imagem aqui

4. Razões para ociosidade da CPU

  • O aplicativo é bloqueado pela primitiva de sincronização e não pode continuar a execução até que o bloqueio seja liberado.
  • O aplicativo está aguardando algo, como uma resposta de uma chamada ao banco de dados.
  • O aplicativo realmente não faz nada.

5. Execute filas

Cada CPU mantém uma fila de execução de threads. Em teoria, o agendador deveria estar constantemente executando e executando threads. O thread do processo está no estado de suspensão (bloqueado e aguardando E/S) ou no estado executável.

Se o subsistema da CPU estiver sob carga elevada, significa que o agendador do kernel não será capaz de responder às solicitações do sistema em tempo hábil. Faz com que processos executáveis ​​fiquem congestionados na fila de execução. À medida que a fila de execução aumenta, os threads do processo gastarão mais tempo sendo executados.

Nota: Cada processador não deve executar mais do que 1-3 threads na fila. Por exemplo, um processador dual-core não deve ter mais de 6 threads na fila de execução.

A fila de execução contém processos leves que estão prontos para execução e aguardando CPU disponível. Se o número de processos leves prontos para execução exceder o limite superior que o sistema pode suportar, a fila de execução será muito longa. A carga do sistema de nomes de tabelas longas da fila de execução pode estar saturada.

**Quando o comprimento da fila de execução do sistema é igual ao número de processadores virtuais, os usuários não notarão nenhuma degradação no desempenho. **O número de processadores virtuais aqui é o número de threads de hardware do sistema. Esse é o valor de retorno de Java API Runtime.availableProcessors(). Quando o comprimento da fila de execução atinge 4 vezes ou mais que o processamento virtual, a resposta do sistema é muito lenta.

O princípio orientador geral é: Se o comprimento da fila de execução for superior a 1 vez o número de processadores virtuais por um longo período de tempo, você precisa prestar atenção. Se for 3 a 4 vezes, você precisa prestar atenção ou tome medidas imediatamente.

5.1. Dois métodos para resolver a fila de longa duração

  • Aumentar a CPU para compartilhar a carga ou reduzir a quantidade de carga no processador reduz fundamentalmente o número de threads ativos em cada processador virtual, reduzindo assim o número de processos leves na fila de execução.

  • Pesquise maneiras de reduzir os ciclos de CPU necessários para executar seu aplicativo, como reduzir a frequência da coleta de lixo ou usar algoritmos que executem a mesma tarefa com menos instruções de CPU.

5.2. Use top para visualizar o status detalhado da fila de execução

Carga refere-se à combinação de quantos threads estão na fila da CPU e quantos threads de processo estão em execução no momento.
Carga = número de processos leves em execução + número de processos leves na fila de execução.
Por exemplo: se um sistema dual-core executa 2 threads e 4 estão na fila de execução, a carga deve ser 6.

As médias de carga exibidas na parte superior referem-se às condições de carga dentro de 1 minuto, 5 minutos e 15 minutos, respectivamente. Se a CPU for single-core, então o valor que excede 1 é carga alta. Se a CPU for quad-core, então A valor acima de 4 indica carga alta.

Palavra de experiência: Se uma CPU tiver um número total de núcleos = 8 núcleos e a carga média teórica chegar a 16, ela ainda pode durar muito tempo.

5.3. Use vmstat para verificar o comprimento da fila de execução

A saída da primeira coluna por vmstat é o comprimento da fila de execução e o valor é o número real de processos leves na fila de execução.

Insira a descrição da imagem aqui

6. Mudanças de contexto

Mesmo uma CPU de núcleo único pode suportar a execução de código multithread.A CPU implementa esse mecanismo alocando intervalos de tempo de CPU para cada thread. O intervalo de tempo é o tempo alocado pela CPU para cada thread. Como o intervalo de tempo é muito curto, a CPU continua alternando os threads para execução, fazendo-nos sentir que vários threads estão sendo executados ao mesmo tempo. O intervalo de tempo geralmente é de dezenas de milissegundos.

A CPU executa tarefas ciclicamente por meio do algoritmo de alocação de intervalo de tempo. Depois que a tarefa atual executa um intervalo de tempo, ela muda para a próxima tarefa. No entanto, o estado da tarefa anterior é salvo antes de alternar para que na próxima vez que você voltar para esta tarefa, você pode carregá-la novamente. O status da tarefa. Portanto, o processo de salvar até recarregar uma tarefa é uma troca de contexto, e a troca de contexto de thread geralmente consome centenas de ciclos de clock .

Como reduzir a mudança de contexto

  1. Na programação simultânea sem bloqueio, a troca de contexto ocorrerá quando vários threads competirem por bloqueios.
  2. Algoritmo CAS, porque nenhum bloqueio é necessário.
  3. Use threads mínimos.
  4. Corrotinas: implemente o agendamento multitarefa em um único thread e mantenha a alternância entre várias tarefas em um único thread.

A maioria dos processadores modernos são capazes de executar um processo (thread único) ou threads. Processadores multithread têm a capacidade de executar vários threads. No entanto, o kernel do Linux ainda trata cada núcleo do processador do chip dual-core como um processador separado. Por exemplo, um sistema com kernel Linux em um processador dual-core é relatado como dois processadores separados.

Um kernel Linux padrão pode executar de 50 a 50.000 threads de processamento . Com apenas uma CPU, o kernel agenda e equilibra cada thread do processo. Cada thread recebe uma cota de tempo para passar no processador. Um thread recebeu uma cota de tempo ou antecipou algo com prioridade mais alta (como uma interrupção de hardware), na qual o thread de prioridade mais alta será realocado da zona de volta para a fila do processador. Esse relacionamento de conversão de thread é a mudança de contexto que mencionamos.

Cada vez que o contexto do kernel muda, recursos são usados ​​para fechar o thread no registro da CPU e colocá-lo na fila. Quanto mais mudanças de contexto houver no sistema, mais trabalho o kernel terá sob o gerenciamento de agendamento do processador.

O número de trocas de contexto está diretamente relacionado ao uso da CPU. Se a utilização da CPU for mantida em um estado equilibrado (65% - 70% do tempo do usuário, 30% - 35% do tempo do sistema, 0% - 5% do tempo ocioso), um grande número de trocas de contexto A troca é normal .

A troca de contexto é dividida em:

  • Troca preemptiva de contexto
  • Troca de contexto concessiva

A troca concessiva de contexto significa que o thread de execução libera ativamente a CPU . A troca preemptiva de contexto significa que o thread é forçado a desistir da CPU ou é preemptado por outros threads de prioridade mais alta porque o intervalo de tempo alocado está esgotado .

Uma alta taxa de troca de contexto preemptiva indica que há mais threads prontos para execução do que processadores virtuais disponíveis. Neste momento, geralmente você pode ver uma fila de longa execução, alto uso de CPU, um grande número de migrações e um grande número de conexões com trocas de contexto preemptivas relacionadas ao vmstat.

7. Monitore as mudanças de contexto

monitoramento vmstat:

Insira a descrição da imagem aqui

monitoramento pidstat -w:

Insira a descrição da imagem aqui

wt Visualize a alternância de contexto em nível de thread:

Insira a descrição da imagem aqui

pidstat -w relata gerando mudanças de contexto por segundo, em vez de por intervalo de medição.
pidstat -w é uma opção de contexto para todos os processadores.

cswch/s é uma troca de contexto concessional
nvcswch/s é uma troca de contexto preemptiva

Diretriz geral: Se as trocas de contexto produtivas ocuparem 5% ou mais de seus ciclos de clock, o aplicativo Java está enfrentando contenção de bloqueio. Mesmo 3% a 5% merecem uma investigação mais aprofundada.

Nas versões anteriores ao Java 5, o HotSpotVM delegava quase toda a lógica de bloqueio às primitivas de bloqueio do sistema operacional, o que permitia que as ferramentas do sistema operacional monitorassem o estado do sistema, uso da CPU e smtx (número de giros no mutex Spin on Mutex). a contenção de bloqueio em aplicativos Java pode ser facilmente monitorada.

Em Java5, o HotSpotVM implementa muitas lógicas de otimização de bloqueio, métodos de sincronização Java e blocos de sincronização na forma de código de usuário. Portanto, o método anterior de usar mpstat para verificar o uso da CPU dos estados do sistema smtx e sys não pode ser usado e novas alternativas precisam ser encontradas.

Em Java 5 e superior,se o bloqueio não for adquirido após várias voltas de loop ocupado,o fio é suspenso e espera para ser despertado antes de tentar adquirir o bloqueio novamente.Suspender e acordar o fio causará uma mudança de contexto concessional pelo operador sistema, portanto, bloqueie a competição. Aplicativos severos exibirão um grande número de trocas de contexto de troca mútua.

O custo do ciclo de clock de uma troca de contexto produtiva é muito alto, geralmente até 80.000 ciclos de clock (esses ciclos de clock poderiam ter sido usados ​​para executar instruções de programa).

O número de ciclos de clock desperdiçados pela produção de trocas de contexto pode ser calculado dividindo o número de trocas de contexto produtivas em pidstat -w pelo número de processadores virtuais. Nota: pidstat -w é uma opção de contexto produtiva para todos os processadores virtuais. Multiplique o número de trocas de contexto concessionais por 80.000 e divida-o pelos ciclos de clock da CPU por segundo para obter a porcentagem de ciclos de clock da CPU consumidos pela troca de contexto concessional.

Ciclos de clock estimados gastos por uma troca de contexto produtiva:

Por exemplo: o número de trocas de contexto concessionais é 8.000/s, 8.000*80.000 (custo do ciclo de clock da troca de contexto geral) = 640.000.000 de ciclos de clock, um processador de 3,0 GHz pode executar 3.000.000.000 (3 bilhões) de ciclos de clock por segundo ciclos, então 640.000.000/3.000.000.000 = 21,33% dos ciclos de clock disponíveis. Isso significa que o aplicativo Java está enfrentando competição de bloqueio. A competição de bloqueio pode ocorrer porque vários threads estão acessando o mesmo método sincronizado ou bloco sincronizado, ou pode ser porque o código é protegido por uma estrutura de bloqueio Java, como java.util.concurrent .locks.Lock.

Por exemplo: cswch/s=3500, existem 2 processadores, então a troca de contexto de cada processador é 3500/2=1750 e os ciclos de clock consumidos são 1750*80000=140 000 000. O número de ciclos de clock por segundo para uma CPU de 3 GHz equivale a 3.000.000.000, então os ciclos de clock desperdiçados pela troca de contexto são 140.000.000/3.000.000.000 = 4,7%, indicando que o aplicativo Java está enfrentando competição de bloqueio.

8. Como verificar qual CPU está ocupada por um processo

while :; do  ps -eo pid,ni,pri,pcpu,psr,comm | grep 'python'; sleep 1;done

[Falha na transferência da imagem do link externo. O site de origem pode ter um mecanismo anti-leeching. Recomenda-se salvar a imagem e carregá-la diretamente (img-eXe2rYzA-1657590066014) (/Users/zy/Desktop/Notes/Performance Test/ imagem-20220712092414388.png)]
Insira a descrição da imagem aqui

Conforme mostrado na figura, a coluna psr indica qual CPU o processo ocupa. Conforme mostrado na figura, parte do processo python3 ocupa a primeira CPU e parte ocupa a segunda CPU.

9. Visualize informações da CPU

[root@iZbp1aqn43v9f9y956pim1Z huyan]# cat /proc/cpuinfo 
processor       : 0 //逻辑核数量
vendor_id       : GenuineIntel
cpu family      : 6
model           : 85
model name      : Intel(R) Xeon(R) Platinum 8269CY CPU @ 2.50GHz //cpu的名称型号和主频
stepping        : 7
microcode       : 0x1
cpu MHz         : 2500.000 //实际主频
cache size      : 36608 KB
physical id     : 0 //单个cpu的标号
siblings        : 2 //单个cpu的逻辑核数
core id         : 0
cpu cores       : 1 //逻辑核所处cpu的物理核
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 arat avx512_vnni
bogomips        : 5000.00
clflush size    : 64
cache_alignment : 64
address sizes   : 46 bits physical, 48 bits virtual
power management:

processor       : 1
vendor_id       : GenuineIntel
cpu family      : 6
model           : 85
model name      : Intel(R) Xeon(R) Platinum 8269CY CPU @ 2.50GHz
stepping        : 7
microcode       : 0x1
cpu MHz         : 2500.000
cache size      : 36608 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 1
apicid          : 1
initial apicid  : 1
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 arat avx512_vnni
bogomips        : 5000.00
clflush size    : 64
cache_alignment : 64
address sizes   : 46 bits physical, 48 bits virtual
power management:

Verifique o número total de CPUs na máquina:

[root@iZbp1aqn43v9f9y956pim1Z huyan]# cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
1

Verifique o número de núcleos físicos de uma única CPU:

[root@iZbp1aqn43v9f9y956pim1Z huyan]# cat /proc/cpuinfo| grep "cpu cores"| uniq
cpu cores       : 1

Verifique o número total de núcleos lógicos:

[root@iZbp1aqn43v9f9y956pim1Z huyan]# cat /proc/cpuinfo| grep "processor"| wc -l
2

Acho que você gosta

Origin blog.csdn.net/u011090984/article/details/125736619
Recomendado
Clasificación