$ time foo
real 0m0.003s
user 0m0.000s
sys 0m0.004s
$
O que significam 'real', 'user' e 'sys' na saída do tempo?
Qual deles é significativo ao comparar meu aplicativo?
unix
time
benchmarking
rayryeng
fonte
fonte
time
, faça algo que levará pelo menos um segundo.time
é uma palavra-chave bash. Então digitaçãoman time
é não dar-lhe uma página de homem para a festançatime
, ao contrário, está dando a página man/usr/bin/time
. Isso me tropeçou.Respostas:
Estatísticas de tempo de processo real, de usuário e de sistema
Uma dessas coisas não é igual as outras. Real refere-se ao tempo decorrido real; Usuário e sistema referem-se ao tempo da CPU usado apenas pelo processo.
Real é a hora do relógio de parede - hora do início ao fim da chamada. Todo esse tempo decorrido, incluindo intervalos de tempo usados por outros processos e o tempo que o processo passa bloqueado (por exemplo, se estiver aguardando a conclusão da E / S).
Usuário é a quantidade de tempo de CPU gasto no código do modo de usuário (fora do kernel) dentro do processo. Este é apenas o tempo real da CPU usado na execução do processo. Outros processos e tempo que o processo gasta bloqueado não contam para esse valor.
Sys é a quantidade de tempo de CPU gasto no kernel dentro do processo. Isso significa executar o tempo de CPU gasto em chamadas do sistema no kernel, em oposição ao código da biblioteca, que ainda está sendo executado no espaço do usuário. Como 'usuário', esse é apenas o tempo da CPU usado pelo processo. Veja abaixo uma breve descrição do modo kernel (também conhecido como modo 'supervisor') e o mecanismo de chamada do sistema.
User+Sys
informará quanto tempo de CPU real seu processo usou. Observe que isso ocorre em todas as CPUs; portanto, se o processo tiver vários encadeamentos (e esse processo estiver sendo executado em um computador com mais de um processador), poderá potencialmente exceder o tempo do relógio de parede relatado porReal
(o que geralmente ocorre). Observe que, na saída, esses números incluem o tempoUser
e oSys
tempo de todos os processos filhos (e seus descendentes), bem como quando eles poderiam ter sido coletados, por exemplo, porwait(2)
ouwaitpid(2)
, embora as chamadas do sistema subjacente retornem as estatísticas para o processo e seus filhos separadamente.Origens das estatísticas relatadas por
time (1)
As estatísticas relatadas por
time
são coletadas de várias chamadas do sistema. 'Usuário' e 'Sys' vêm dewait (2)
( POSIX ) outimes (2)
( POSIX ), dependendo do sistema específico. 'Real' é calculado a partir das horas de início e término coletadas nagettimeofday (2)
chamada. Dependendo da versão do sistema, várias outras estatísticas, como o número de alternâncias de contexto, também podem ser coletadastime
.Em uma máquina com vários processadores, um processo com vários threads ou um processo de bifurcação de crianças pode ter um tempo decorrido menor que o tempo total da CPU - pois diferentes threads ou processos podem ser executados em paralelo. Além disso, as estatísticas de tempo relatadas são de origens diferentes; portanto, os tempos registrados para tarefas de execução muito curtas podem estar sujeitos a erros de arredondamento, como mostra o exemplo dado pelo pôster original.
Uma breve cartilha no modo Kernel vs. Usuário
No Unix, ou em qualquer sistema operacional com memória protegida, o modo 'Kernel' ou 'Supervisor' refere-se a um modo privilegiado no qual a CPU pode operar. Certas ações privilegiadas que podem afetar a segurança ou a estabilidade só podem ser executadas quando a CPU está operando em este modo; essas ações não estão disponíveis para o código do aplicativo. Um exemplo dessa ação pode ser a manipulação da MMU para obter acesso ao espaço de endereço de outro processo. Normalmente, o código do modo de usuário não pode fazer isso (por um bom motivo), embora possa solicitar memória compartilhada do kernel, o que poderiaser lido ou escrito por mais de um processo. Nesse caso, a memória compartilhada é solicitada explicitamente ao kernel através de um mecanismo seguro e os dois processos precisam se conectar explicitamente a ele para usá-lo.
O modo privilegiado é geralmente chamado de modo 'kernel' porque o kernel é executado pela CPU em execução nesse modo. Para alternar para o modo kernel, é necessário emitir uma instrução específica (geralmente chamada armadilha ) que alterna a CPU para execução no modo kernel e executa código de um local específico mantido em uma tabela de salto. Por motivos de segurança, você não pode alternar para o modo kernel e executar código arbitrário - os traps são gerenciados através de uma tabela de endereços que não podem ser gravados, a menos que a CPU esteja executando no modo supervisor. Você trap com um número explícito de trap e o endereço é procurado na tabela de salto; o kernel possui um número finito de pontos de entrada controlados.
As chamadas de 'sistema' na biblioteca C (principalmente as descritas na Seção 2 das páginas de manual) possuem um componente no modo de usuário, que é o que você realmente chama no seu programa C. Nos bastidores, eles podem emitir uma ou mais chamadas de sistema para o kernel para executar serviços específicos, como E / S, mas ainda possuem código em execução no modo de usuário. Também é possível emitir diretamente uma interceptação no modo kernel a partir de qualquer código de espaço do usuário, se desejado, embora seja necessário escrever um trecho da linguagem assembly para configurar os registradores corretamente para a chamada.
Mais sobre 'sys'
Há coisas que seu código não pode fazer no modo usuário - como alocar memória ou acessar hardware (HDD, rede etc.). Eles estão sob a supervisão do kernel, e só eles podem fazê-lo. Algumas operações como
malloc
oufread
/fwrite
invocam essas funções do kernel e que contam como tempo 'sys'. Infelizmente, não é tão simples como "todas as chamadas para malloc serão contadas no tempo 'sys'". A chamada paramalloc
fará algum processamento próprio (ainda contado no tempo de 'usuário') e, em algum momento do processo, poderá chamar a função no kernel (contada no tempo de 'sys'). Depois de retornar da chamada do kernel, haverá mais tempo em 'user' e, em seguida,malloc
retornará ao seu código. Quanto a quando o switch acontece, e quanto dele é gasto no modo kernel ... você não pode dizer. Depende da implementação da biblioteca. Além disso, outras funções aparentemente inocentes também podem usarmalloc
e afins em segundo plano, que terão novamente algum tempo em 'sys'.fonte
Para expandir a resposta aceita , eu só queria fornecer outro motivo para o
real
≠user
+sys
.Tenha em mente que
real
representa o tempo decorrido real, enquantouser
esys
valores representam o tempo de execução da CPU. Como resultado, em um sistema multicore, o tempouser
e / ousys
(assim como sua soma) pode realmente exceder o tempo real. Por exemplo, em um aplicativo Java que estou executando para a classe, recebo este conjunto de valores:fonte
real
excederuser
esys
total? Sobrecarga do sistema operacional, como a alternância de contexto de thread pode ser?• real : o tempo real gasto na execução do processo do início ao fim, como se fosse medido por um ser humano com um cronômetro
• usuário : o tempo acumulado gasto por todas as CPUs durante o cálculo
• sys : o tempo acumulado gasto por todas as CPUs durante tarefas relacionadas ao sistema, como alocação de memória.
fonte
sys
é CPU-tempo gasto em chamadas de sistema (e manipuladores de falta de página?)real
é frequentemente descrito como hora de "relógio de parede".Exemplos mínimos de POSIX C executáveis
Para tornar as coisas mais concretas, quero exemplificar alguns casos extremos de
time
alguns programas de teste C mínimos.Todos os programas podem ser compilados e executados com:
e foram testados no Ubuntu 18.10, GCC 8.2.0, glibc 2.28, Linux kernel 4.18, laptop ThinkPad P51, CPU Intel Core i7-7820HQ (4 núcleos / 8 threads), 2x Samsung M471A2K43BB1-CRC RAM (2x 16GiB).
dormir
O sono não ocupado não conta apenas em um
user
ou emsys
apenas umreal
.Por exemplo, um programa que dorme por um segundo:
GitHub upstream .
produz algo como:
O mesmo vale para os programas bloqueados quando o IO está disponível.
Por exemplo, o seguinte programa aguarda o usuário digitar um caractere e pressione enter:
GitHub upstream .
E se você esperar cerca de um segundo, o resultado será igual ao exemplo de suspensão, algo como:
Por esse motivo,
time
pode ajudá-lo a distinguir entre programas vinculados à CPU e E / S: O que significam os termos "vinculado à CPU" e "vinculado à E / S"?Vários segmentos
O exemplo a seguir faz
niters
iterações de trabalho inútil puramente vinculado à CPU emnthreads
threads:GitHub upstream + código de plotagem .
Em seguida, plotamos wall, user e sys em função do número de threads para 10 iterações fixas de 10 ^ 10 na minha CPU hyperthread de 8:
Plotar dados .
A partir do gráfico, vemos que:
para um aplicativo de núcleo único intensivo de CPU, parede e usuário são praticamente os mesmos
para 2 núcleos, o usuário tem cerca de duas paredes, o que significa que o tempo do usuário é contado em todos os segmentos.
o usuário basicamente dobrou e, enquanto o muro permaneceu o mesmo.
isso continua até 8 threads, o que corresponde ao meu número de hyperthreads no meu computador.
Depois das 8, o muro começa a aumentar também, porque não temos CPUs extras para colocar mais trabalho em um determinado período de tempo!
A razão de platôs neste momento.
Observe que este gráfico é tão claro e simples porque o trabalho é puramente vinculado à CPU: se fosse vinculado à memória, teríamos uma queda no desempenho muito mais cedo com menos núcleos, porque os acessos à memória seriam um gargalo, como mostrado em O que os termos "CPU bound" e "I / O bound" significam?
Sys trabalho pesado com
sendfile
A carga de trabalho mais pesada do sistema que eu pude criar foi usar o
sendfile
, que executa uma operação de cópia de arquivo no espaço do kernel: Copie um arquivo de maneira sã, segura e eficienteEntão, imaginei que esse kernel
memcpy
seria uma operação intensiva da CPU.Primeiro, inicializo um arquivo aleatório grande de 10 GiB com:
Em seguida, execute o código:
GitHub upstream .
que fornece basicamente o tempo do sistema conforme o esperado:
Eu também estava curioso para ver se
time
distinguiria os syscalls de diferentes processos, então tentei:E o resultado foi:
O tempo do sistema é praticamente o mesmo para um único processo, mas o tempo da parede é maior porque os processos estão competindo pelo acesso de leitura do disco.
Portanto, parece que de fato explica qual processo iniciou um determinado trabalho do kernel.
Código-fonte Bash
Quando você faz apenas
time <cmd>
no Ubuntu, ele usa a palavra-chave Bash, como pode ser visto em:quais saídas:
Então nós grep source no código-fonte do Bash 4.19 para a string de saída:
o que nos leva à função execute_cmd.c
time_command
, que usa:gettimeofday()
egetrusage()
se ambos estiverem disponíveistimes()
de outra formatodas chamadas de sistema Linux e funções POSIX .
Código fonte GNU Coreutils
Se o chamarmos como:
então ele usa a implementação GNU Coreutils.
Este é um pouco mais complexo, mas a fonte relevante parece estar em resuse.c e funciona:
wait3
chamada BSD não POSIX, se disponíveltimes
e degettimeofday
outra formafonte
Real mostra o tempo total de retorno de um processo; enquanto o usuário mostra o tempo de execução das instruções definidas pelo usuário e o Sys é o tempo de execução das chamadas do sistema!
O tempo real também inclui o tempo de espera (o tempo de espera para E / S, etc.)
fonte