Diferença entre CLOCK_REALTIME e CLOCK_MONOTONIC?


206

Você poderia explicar a diferença entre CLOCK_REALTIMEe os CLOCK_MONOTONICrelógios retornados clock_gettime()no Linux?

Qual é a melhor opção se eu precisar calcular o tempo decorrido entre os carimbos de data e hora produzidos por uma fonte externa e o horário atual?

Por fim, se eu tenho um daemon NTP ajustando periodicamente a hora do sistema, como esses ajustes interagem com cada um deles CLOCK_REALTIMEe CLOCK_MONOTONIC?

Respostas:


238

CLOCK_REALTIMErepresenta a melhor estimativa da máquina para o relógio de parede atual, a hora do dia. Como dizem Ignacio e MarkR , isso significa que CLOCK_REALTIMEpode avançar e retroceder à medida que o relógio da hora do dia do sistema é alterado, inclusive pelo NTP.

CLOCK_MONOTONICrepresenta o tempo absoluto decorrido do relógio de parede desde algum ponto fixo arbitrário no passado. Não é afetado por alterações no relógio da hora do dia do sistema.

Se você deseja calcular o tempo decorrido entre dois eventos observados em uma máquina sem uma reinicialização intermediária, CLOCK_MONOTONICé a melhor opção.

Observe que no Linux, CLOCK_MONOTONICnão mede o tempo gasto em suspensão, embora pela definição do POSIX deva. Você pode usar o específico do Linux CLOCK_BOOTTIMEpara um relógio monotônico que continua em execução durante a suspensão.


11
Observe que nos kernels mais recentes, CLOCK_MONOTONIC_RAW está disponível, o que é ainda melhor (sem ajustes de NTP).
Joseph Garvin

14
@ JosephphGarvin por algum valor de "melhor", talvez - CLOCK_MONOTONIC_RAW pode rodar rápido ou devagar em tempo real em várias (ou várias centenas) partes por milhão, e sua taxa pode variar devido a condições ambientais como temperatura ou tensão (ou tempo de roubo) máquinas virtuais). Em uma máquina que funciona adequadamente, o NTP faz o possível para mitigar todos esses fatores e, portanto, CLOCK_MONOTONIC reflete mais de perto o tempo decorrido real .
precisa

23
É verdade que pode ser interessante ter um CLOCK_MONOTONIC_PARBOILED afetado pelos esforços do NTP para corrigir erros de frequência, mas não afetado por seus esforços para corrigir erros de fase, mas isso é muita complexidade para um ganho duvidoso :)
hobbs

1
Eu gosto do ponto que @hobbs traz à tona. E se você estiver preocupado com os programas que podem ser afetados pelo desvio do relógio? Seria CLOCK_MONOTONICa melhor escolha nesse cenário? por exemplo, Patriot Missile System
sjagr

3
Eu também acho importante mencionar que CLOCK_REALTIME é afetado por segundos de salto. Isso significa que ele irá produzir o dobro timestamps cada vez que é inserido um segundo salto. A última vez que isso aconteceu em 30 de junho de 2012 e um monte de software teve problemas .
user1202136

38

O livro de Robert Love, LINUX System Programming 2nd Edition , aborda especificamente sua pergunta no início do capítulo 11, página 363:

O aspecto importante de uma fonte de tempo monotônica NÃO é o valor atual, mas a garantia de que a fonte de tempo está aumentando estritamente linearmente e, portanto, útil para calcular a diferença de tempo entre duas amostragens

Dito isso, acredito que ele esteja assumindo que os processos estão em execução na mesma instância de um sistema operacional; portanto, convém executar uma calibração periódica para estimar a deriva.


25

CLOCK_REALTIMEé afetado pelo NTP e pode se mover para frente e para trás. CLOCK_MONOTONICnão é, e avança em um tick por tick.


15
CLOCK_MONOTONIC é afetado pelo ajuste de hora do NTP (rotação do tempo). Não vai pular, no entanto.
Derobert 23/08

3
Mas nos kernels mais recentes, há CLOCK_MONOTONIC_RAW, que realmente não é afetado pelo NTP.
Joseph Garvin

1
"tick" - alguma idéia aproximada de quão grande / longa / instruções de CPU é um tick no Linux / amd64? Ou onde posso obter documentos sobre isso?
Kevinarpe

@ kevinarpe Não tenho certeza, mas acho que um tiquetaque é definido como uma fração de tempo, não um número de ciclos de CPU, geralmente é de 1/100 segundo.
Stéphane

@ Stéphane: Eu certamente devo estar mais apertado que 10ms. Eu acho que o Java System.nanoTime()usa CLOCK_MONOTONICe pode medir durações de 1000ns ou menos. Talvez você esteja pensando na hora do sistema, que às vezes é limitada a milissegundos?
Kevinarpe #

20

Além da resposta de Ignacio , CLOCK_REALTIMEpode avançar em saltos e, ocasionalmente, para trás. CLOCK_MONOTONICnão faz; ele continua avançando (embora provavelmente seja redefinido na reinicialização).

Um aplicativo robusto precisa ser capaz de tolerar CLOCK_REALTIMEsaltar para a frente ocasionalmente (e talvez para trás muito ligeiramente, muito ocasionalmente, embora isso seja mais um exemplo de caso).

Imagine o que acontece quando você suspende o laptop - CLOCK_REALTIMEsalta para a frente seguindo o resumo,CLOCK_MONOTONIC não. Experimente em uma VM.


3
CLOCK_MONOTONIC inicia em 0 quando o programa é iniciado; não é para uso entre processos.
Benubird

18
@ Benubird: Ele não inicia em 0 quando o programa é iniciado. É isso CLOCK_PROCESS_CPUTIME_ID. Teste rápido: $ perl -w -MTime::HiRes=clock_gettime,CLOCK_MONOTONIC -E 'say clock_gettime(CLOCK_MONOTONIC)'-> 706724.117565279. Esse número corresponde ao tempo de atividade do sistema no Linux, mas o padrão diz que é arbitrário.
derobert

4
Como um aparte, não acredito que o comportamento do Linux em que CLOCK_MONOTONICinterrompa uma suspensão / retomada seja compatível com POSIX. Supõe-se que é o tempo desde um ponto fixo no passado, mas parar o relógio ao suspender / retomar interrompe isso.
Caf

15

POSIX 7 quotes

O POSIX 7 especifica ambos em http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html :

CLOCK_REALTIME:

Este relógio representa o relógio que mede em tempo real para o sistema. Para esse relógio, os valores retornados por clock_gettime () e especificados por clock_settime () representam a quantidade de tempo (em segundos e nanossegundos) desde a época.

CLOCK_MONOTONIC (recurso opcional):

Para esse relógio, o valor retornado por clock_gettime () representa a quantidade de tempo (em segundos e nanossegundos) desde um ponto não especificado no passado (por exemplo, hora de inicialização do sistema ou época). Este ponto não muda após o tempo de inicialização do sistema. O valor do relógio CLOCK_MONOTONIC não pode ser definido via clock_settime ().

clock_settime()dá uma dica importante: os sistemas POSIX podem mudar arbitrariamente CLOCK_REALITMEcom ele, portanto, não confie nele fluindo nem continuamente nem para frente. O NTP pode ser implementado usando clock_settime()e só pode afetar CLOCK_REALITME.

A implementação do kernel Linux parece levar o tempo de inicialização como a época para CLOCK_MONOTONIC: Ponto de partida para CLOCK_MONOTONIC


0

Desculpe, não há reputação de adicionar isso como um comentário. Por isso, é uma resposta complementar.

Dependendo da frequência com que você liga clock_gettime(), lembre-se de que apenas alguns dos "relógios" são fornecidos pelo Linux no VDSO (ou seja, não exigem um syscall com toda a sobrecarga de um - o que só piorou quando o Linux foi adicionado as defesas para proteger contra ataques do tipo Espectro).

Enquanto clock_gettime(CLOCK_MONOTONIC,...), clock_gettime(CLOCK_REALTIME,...)e gettimeofday()são sempre vai ser extremamente rápida (acelerada pela VDSO), este é não verdadeiro para, por exemplo CLOCK_MONOTONIC_RAW ou qualquer um dos outros relógios POSIX.

Isso pode mudar com a versão do kernel e a arquitetura.

Embora a maioria dos programas não precise prestar atenção nisso, pode haver picos de latência nos relógios acelerados pelo VDSO: se você pressioná-los exatamente quando o kernel está atualizando a área de memória compartilhada com os contadores de clock, ele deve esperar pelo kernel para terminar.

Aqui está a "prova" (GitHub, para manter os bots longe do kernel.org): https://github.com/torvalds/linux/commit/2aae950b21e4bc789d1fc6668faf67e8748300b7


0

CLOCK_REALTIME : Tempo absoluto (por exemplo, 07/01/2020)

CLOCK_MONOTONIC: Tempo relativo (por exemplo, daqui a 5 segundos ou 10 minutos atrás)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.