No meu entendimento, time
registraria o tempo total gasto em syscalls. Então, eu esperaria que os totais cumulativos para o tempo do sistema, conforme relatado por time
e strace -fc
, fossem os mesmos. Mas eles são muito diferentes (13,5 vs 0,005). O que está acontecendo?
# time php index.php >/dev/null
real 0m16.292s
user 0m2.728s
sys 0m13.548s
# strace -fc php index.php >/dev/null
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
83.72 0.000365 0 54845 munmap
10.09 0.000044 0 36705 mmap
6.19 0.000027 0 18249 madvise
0.00 0.000000 0 289 read
0.00 0.000000 0 119 write
0.00 0.000000 0 118 3 open
0.00 0.000000 0 118 close
0.00 0.000000 0 23 stat
[ cut 0 duration syscalls for brevity ]
100.00 0.000436 110951 82 total
(Eu executei novamente esses testes cerca de 50 vezes e ambos deram resultados consistentes)
Um processo pode gastar qualquer quantidade de tempo sem fazer nenhuma chamada de sistema.
Por exemplo, um shell fazendo um
while :; do :; done
gastará uma quantidade infinita de tempo sem fazer nenhuma chamada de sistema e sem gastarsys
tempo de CPU, apenasuser
tempo de CPU.strace -c
tenta contar osys
tempo de CPU por cada chamada do sistema. Ananosleep(1000000000)
gastará cerca de 0ms de tempo de CPU, mas 1s de tempo de relógio de parede.Comparar o tempo do sistema com o tempo relatado pelo strace faria mais sentido, mas observe que nem todo o tempo de CPU do sistema contabilizado para o processo é gasto nesses syscalls. Acessar dados mapeados, por exemplo, pode fazer com que o processo gaste muito tempo do sistema sem fazer nenhuma chamada do sistema.
Aqui, essas inúmeras
mmaps()
chamadas podem ser para alocar memória. Esses são instantâneos, pois apenas atualizam alguns mapeamentos. Mas a primeira vez que você escreve para eles, é aí que algum tempo do sistema é necessário para fazer backup dessas gravações com a memória real.Ou podem ser para mapear arquivos de objeto como bibliotecas compartilhadas (essa também é uma possibilidade provável, pois o número não está longe do número de
open()s
). Então, novamente, ommap()
é rápido, mas ler a memória mais tarde também significa algumas falhas de página e tempo real para ler os dados do disco, o que não é contabilizado em nenhuma chamada do sistema.Mais fundamentalmente, se você fizer
time strace -f your-application
como em uma versão anterior de sua pergunta,time
cronometrará o comando estrace
.strace
adiciona muita sobrecarga. Ele faz algumas chamadas de sistema para cada chamada de sistema do aplicativo rastreado.Fazendo
ao invés de
é mais provável que lhe dê uma correspondência melhor.
O que descobri, porém, é que para as
wait*()
chamadas de sistema que os processos fazem para esperar seus filhos,strace
conta o tempo relatado por essaswait*()
chamadas de sistema como tempo do sistema, o que significa que o tempo dos processos filhos (pelo menos os que são esperados) é contado várias vezes. Isso é importante,strace -f time cmd
poistime
é executadocmd
em um processo filho e aguarda por ele.time
estrace
relatar o mesmo horário do sistema (conforme retornado pelawait4()
chamada do sistema), mas com-f
:O 1,33 é o tempo relatado pela única
wait4()
chamada de sistema que otime
faz. Isso informa o tempo do sistema dehead
(time
filho de).No entanto,
strace
também tenta obter o tempo do sistema para cada syscall de seuhead
neto, o que significa que é contado duas vezes (não exatamente). Esse traçado do neto ainda incorre em alguma sobrecarga contabilizada no processo traçado, pois obtemos 1,33 em oposição a 0,76 anteriormente. Isso é consideravelmente reduzido se eu forçar strace, time e head a rodar no mesmo processador (comtaskset 1
).