Medir o tempo no Linux – tempo vs relógio vs getrusage vs clock_gettime vs gettimeofday vs timespec_get?

Entre as funções de time , time , clock getrusage , clock_gettime , gettimeofday e timespec_get , quero entender claramente como eles são implementados e quais são seus valores de retorno para saber em qual situação eu tenho que usá-los.

Primeiro, precisamos classificar as funções que retornam os valores de relógio de parede para comparar com as funções que retornam valores de processo ou threads . gettimeofday retorna valor de relógio de parede, clock_gettime retorna valor de relógio de parede ou valores de processo ou threads, dependendo do parâmetro Clock passado para ele. getrusage e clock retornam os valores do processo.

Em seguida, a segunda questão diz respeito à implementação dessas funções e, como conseqüência, a sua precisão. Qual mecanismo de hardware ou software essas funções usam?

Parece que o getrusage usa apenas o tick do kernel (geralmente 1 ms de comprimento) e, como conseqüência, não pode ser mais preciso do que o ms. Está certo? Então a function getimeofday parece usar o hardware subjacente mais preciso disponível. Como conseqüência, sua precisão é geralmente o microssegundo (não pode ser mais por causa da API) no hardware recente. E quanto ao clock , a página man fala sobre “aproximação”, o que isso significa? E quanto a clock_gettime , a API está em nanossegundos, isso significa que ela pode ser tão precisa se o hardware subjacente permitir? E quanto à monotonicidade?

Existem outras funções?

O problema é que existem várias funções de tempo diferentes disponíveis em C e C ++, e algumas delas variam em comportamento entre implementações. Há também muitas meias respostas flutuando. Compilar uma lista de funções do relógio junto com suas propriedades responderia a pergunta corretamente. Para começar, vamos perguntar quais são as propriedades relevantes que estamos procurando. Olhando para o seu post, sugiro:

  • Que horas são medidas pelo relógio? (real, usuário, sistema ou, esperançosamente, não, relógio de parede?)
  • Qual a precisão do relógio? (s, ms, µs ou mais rápido?)
  • Depois de quanto tempo o relógio envolve? Ou existe algum mecanismo para evitar isso?
  • O relógio é monotônico ou será alterado com alterações no horário do sistema (via NTP, fuso horário, horário de verão, pelo usuário, etc.)?
  • Como os itens acima variam entre implementações?
  • A function específica é obsoleta, não padrão, etc.?

Antes de iniciar a lista, gostaria de salientar que o relógio de parede raramente é o momento certo de usar, enquanto ele muda com as alterações de fuso horário, o horário de verão muda ou se o relógio de parede é sincronizado pelo NTP. Nenhuma dessas coisas é boa se você estiver usando o tempo para agendar events ou para avaliar o desempenho. É bom apenas para o que o nome diz, um relógio na parede (ou desktop).

Aqui está o que eu encontrei até agora para relógios no Linux e OS X:

  • time() retorna a hora do relógio do sistema operacional, com precisão em segundos.
  • clock() parece retornar a sum do tempo do usuário e do sistema. Está presente no C89 e posterior. Em um momento, esse era o tempo de CPU em ciclos, mas os padrões modernos, como o POSIX, exigem CLOCKS_PER_SEC como 1000000, dando uma precisão máxima possível de 1 µs. A precisão no meu sistema é de fato 1 µs. Este relógio é colocado em funcionamento uma vez terminado (isso normalmente acontece após ~ 2 ^ 32 ticks, o que não é muito longo para um clock de 1 MHz). man clock diz que desde o glibc 2.18 é implementado com clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) no Linux.
  • clock_gettime(CLOCK_MONOTONIC, ...) fornece resolução de nanossegundos, é monótono. Eu acredito que os ‘segundos’ e ‘nanossegundos’ são armazenados separadamente, cada um em contadores de 32 bits. Assim, qualquer wrap-around ocorreria após muitos anos de uptime. Parece um bom relógio, mas infelizmente ainda não está disponível no OS X. O POSIX 7 descreve o CLOCK_MONOTONIC como uma extensão opcional .
  • getrusage() acabou por ser a melhor escolha para a minha situação. Ele informa os horários do usuário e do sistema separadamente e não se ajusta ao redor. A precisão do meu sistema é de 1 µs, mas também testei em um sistema Linux (Red Hat 4.1.2-48 com GCC 4.1.2) e a precisão foi de apenas 1 ms.
  • gettimeofday() retorna a hora do relógio de parede com precisão (nominalmente) µs. No meu sistema, este relógio parece ter precisão µs, mas isso não é garantido, porque “a resolução do relógio do sistema depende do hardware” . POSIX.1-2008 diz isso . clock_gettime() “Aplicativos devem usar a function clock_gettime() invés da obsoleta function gettimeofday() “, então você deve ficar longe dela. Linux x86 e implementa-o como uma chamada de sistema .
  • mach_absolute_time() é uma opção para sincronismo de resolução muito alta (ns) no OS X. No meu sistema, isso realmente fornece resolução de ns. Em princípio, este relógio se desdobra, mas ele está armazenando ns usando um inteiro não assinado de 64 bits, portanto, o envolvimento não deve ser um problema na prática. Portabilidade é questionável.
  • Eu escrevi uma function híbrida baseada neste trecho que usa clock_gettime quando compilado no Linux, ou um timer Mach quando compilado no OS X, a fim de obter precisão de ns no Linux e OS X.

Todos os itens acima existem no Linux e no OS X, exceto onde especificado de outra forma. “Meu sistema” acima é uma Apple rodando o OS X 10.8.3 com o GCC 4.7.2 da MacPorts.

Finalmente, aqui está uma lista de referências que achei útil, além dos links acima:


Atualização : para o OS X, o clock_gettime foi implementado a partir do 10.12 (Sierra). Além disso, as plataformas baseadas em POSIX e BSD (como OS X) compartilham o campo struct rusage.ru_utime .

C11 timespec_get

Exemplo de uso em: https://stackoverflow.com/a/36095407/895245

A máxima precisão possível retornada é de nanossegundos, mas a precisão real é definida pela implementação e pode ser menor.

Retorna o tempo de parede, não o uso da CPU.

O glibc 2.21 o implementa em sysdeps/posix/timespec_get.c e encaminha diretamente para:

 clock_gettime (CLOCK_REALTIME, ts) < 0) 

clock_gettime e CLOCK_REALTIME são POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html , e man clock_gettime diz que esta medida pode ter descontinuidades se você alterar alguma configuração de tempo do sistema enquanto seu programa é executado.

C + + 11 crono

Já que estamos nisso, vamos cobri-los também: http://en.cppreference.com/w/cpp/chrono

GCC 5.3.0 (C ++ stdlib está dentro da origem do GCC):

  • high_resolution_clock é um alias para system_clock
  • system_clock encaminha para o primeiro dos seguintes que está disponível:
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock encaminha para o primeiro dos seguintes que está disponível:
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

Perguntado em: Diferença entre std :: system_clock e std :: steady_clock?

CLOCK_REALTIME vs CLOCK_MONOTONIC : Diferença entre CLOCK_REALTIME e CLOCK_MONOTONIC?