Java & Clocks

Java & Clocks


Lendo o livro “Designing Data-Intensive Applications” aprendi algo muito util em Java. Sabia que System.currentTimeMillis() e System.nanoTime() são duas funcionalidades completamente diferente?

Para entender isso tem que se entender o conceito de Monotonic e Time-of-Day Clocks.

Clock é um sistema independente dentro de qualquer máquina que alimenta um contador independente da CPU. Tem um tick que incrementa esse contador e esse contador é usado para calcular a data.

Data é o número segundos/milissegundos desde do Epoch, que é 1º de janeiro de 1970 00:00:00.

Dá uma lida na documentação do GNU sobre a procedimento clock_gettime. Observa os parâmetros, vê que são dois clocks diferentes?

No CLOCK_REALTIME, vai retornar um contador que é sempre atualizado pelo Sistema Operacional usando o servidor NTP.

No CLOCK_MONOTONIC temos um contador monotonico, isso signitica que não vai ser atualizado pelo NTP.

Quais as implicações disso?

Sempre que você for usar o clock para pegar a data atual, use CLOCK_REALTIME. Ele estará mais próximo da verdade (observer que ele tem um erro).

Sempre que você for calcular tempos de execução, use CLOCK_MONOTONIC. Ele dará o real tempo de execução.

Em Java o System.currentTimeMillis() usa o CLOCK_REALTIME e o System.nanoTime() usa o CLOCK_MONOTONIC.

Isso porque o real time não tem tanta resolução, tem que se descontar a latência da rede entre o seu computador e o servidor NTP.

Imagina o caso abaixo:

long startTime = System.currentTimeMillis();
// ... código ...
long elapsedMillis = System.currentTimeMillis() - startTime;

Durante a execução o SO pode ter atualizado o clock e o elapsedMillis pode até ser negativo.

Já o código abaixo, temos a certeza que não foi atualizado.

long startTime = System.nanoTime();
// ... código ...
long elapsedNanos = System.nanoTime() - startTime;

E se eu quiser o tempo real universal? Acho que Einstein se entristece com essa pergunta, mas blz!

O Google tem uma API chamada TrueTime, que vai retornar a data baseada em vários servidores NTP e um intervalo de erro. Toda medida tem erro no mundo… Aceite!

Mas o TrueTime só é útil em caso de resolução de conflitos de concorrência complexos.

Ainda não achei uma API do TrueTime para Java (só para Android). Também nunca precisei. 😉

Conclusão

Se você quer a data, use System.currentTimeMillis(). Se você quer pegar o timestamp inicial para calcultar um tempo de execução, use System.nanoTime(). É mais confiável.

Originally published October 07, 2021