Los tres relojes

Los tres relojes

Un reloj consta de un punto de partida y un tictac de tiempo. C++ ofrece con std::chrono::system_clock, std::chrono::steady_clock y std::chrono::high_solution_clock tres relojes.

Los relojes

Debido a tres relojes diferentes, surge la pregunta:¿Cuáles son las diferencias?

  • std::crono::sistema_reloj: Es el reloj de tiempo real de todo el sistema (reloj de pared). El reloj tiene las funciones auxiliares to_time_t y from_time_t para convertir puntos de tiempo en fechas.
  • std::crono::steady_clock: Proporciona como solo un reloj la garantía de que no se puede ajustar. Por lo tanto, std::chrono::steady_clock es el reloj preferido para esperar una duración de tiempo o hasta un punto de tiempo.
  • std::crono::reloj_de_alta_resolución: Es el reloj con la mayor precisión, pero puede ser sinónimo del reloj std::chrono::system_clock o std::chrono::steady_clock.

El estándar C++ no ofrece ninguna garantía sobre la precisión, el punto de partida o el intervalo de tiempo válido de los relojes. Normalmente, el punto de partida de std::chrono:system_clock es el 1.1.1970, la llamada época UNIX. Para std::chrono::steady_clock, normalmente el tiempo de arranque de su PC.

Precisión y Estabilidad

Es interesante saber qué relojes son estables y qué precisión proporcionan. Obtienes las respuestas de los relojes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// clockProperties.cpp

#include <chrono>
#include <iomanip>
#include <iostream>

template <typename T>
void printRatio(){ 
 std::cout << " precision: " << T::num << "/" << T::den << " second " << std::endl;
 typedef typename std::ratio_multiply<T,std::kilo>::type MillSec;
 typedef typename std::ratio_multiply<T,std::mega>::type MicroSec;
 std::cout << std::fixed;
 std::cout << " " << static_cast<double>(MillSec::num)/MillSec::den << " milliseconds " << std::endl;
 std::cout << " " << static_cast<double>(MicroSec::num)/MicroSec::den << " microseconds " << std::endl;
}

int main(){
 
 std::cout << std::boolalpha << std::endl;
 
 std::cout << "std::chrono::system_clock: " << std::endl;
 std::cout << " is steady: " << std::chrono::system_clock::is_steady << std::endl;
 printRatio<std::chrono::system_clock::period>();
 
 std::cout << std::endl;
 
 std::cout << "std::chrono::steady_clock: " << std::endl;
 std::cout << " is steady: " << std::chrono::steady_clock::is_steady << std::endl;
 printRatio<std::chrono::steady_clock::period>();
 
 std::cout << std::endl;
 
 std::cout << "std::chrono::high_resolution_clock: " << std::endl;
 std::cout << " is steady: " << std::chrono::high_resolution_clock::is_steady << std::endl;
 printRatio<std::chrono::high_resolution_clock::period>();
 
 
 std::cout << std::endl;
 
}

Muestro en las líneas 22, 28 y 34 para cada reloj si es continuo. Mi trabajo en la función printRatio (líneas 7 - 15) es más desafiante. Primero, muestro la precisión de los relojes en una fracción, segundo en un número flotante. Por lo tanto, uso la plantilla de función std::ratio_multiply y las constantes std::kilo y std::mega para ajustar las unidades a milisegundos y microsegundos. Puede obtener los detalles sobre el cálculo en tiempo de compilación en cppreference.com.

La salida en Linux difiere de la de Windows. std::chrono::system_clock es mucho más preciso en Linux; std::chrono::high_resultion_clock está estable en Windows.

Aunque el estándar C++ no especifica la época del reloj, puedes calcularla.

Época

Gracias a la función auxiliar time_since_epoch, obtienes de cada punto de tiempo cuánto tiempo ha pasado desde la época.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// now.cpp

#include <chrono>
#include <iomanip>
#include <iostream>

template <typename T>
void durationSinceEpoch(T dur){
 std::cout << " Counts since epoch: " << dur.count() << std::endl;
 typedef std::chrono::duration<double, std::ratio<60>> MyMinuteTick;
 MyMinuteTick myMinute(dur);
 std::cout << std::fixed;
 std::cout << " Minutes since epoch: "<< myMinute.count() << std::endl;
 typedef std::chrono::duration<double, std::ratio<60*60*24*365>> MyYearTick;
 MyYearTick myYear(dur);
 std::cout << " Years since epoch: " << myYear.count() << std::endl;
}
 
int main(){
 
 std::cout << std::endl;
 
 std::chrono::system_clock::time_point timeNowSysClock = std::chrono::system_clock::now(); 
 std::chrono::system_clock::duration timeDurSysClock= timeNowSysClock.time_since_epoch();
 std::cout << "std::chrono::system_clock: " << std::endl;
 durationSinceEpoch(timeDurSysClock);
 
 std::cout << std::endl;
 
 auto timeNowStClock = std::chrono::steady_clock::now(); 
 auto timeDurStClock= timeNowStClock.time_since_epoch();
 std::cout << "std::chrono::steady_clock: " << std::endl;
 durationSinceEpoch(timeDurStClock);
 
 std::cout << std::endl;
 
 auto timeNowHiRes = std::chrono::high_resolution_clock::now(); 
 auto timeDurHiResClock= timeNowHiRes.time_since_epoch();
 std::cout << "std::chrono::high_resolution_clock: " << std::endl;
 durationSinceEpoch(timeDurHiResClock);
 
 std::cout << std::endl;

}

Las variables timeDurSysClock (línea 24), timeNowStClock (línea 31) y timeNowHiResClock (Zeile 38) contienen para cada reloj, cuánto tiempo ha pasado desde el punto de inicio del reloj. Cuando no uso la deducción automática de tipo con auto, los tipos explícitos del punto de tiempo y la duración del tiempo son extremadamente detallados para escribir. En la función durationSinceEpoch (líneas 7 - 17), muestro la duración del tiempo en diferentes resoluciones. Primero, muestro la cantidad de tics de tiempo (línea 9), luego la cantidad de minutos (línea 13) y al final de los años (línea 16) desde la época, todo dependiendo del reloj utilizado. Ignoro los años bisiestos por razones de simplicidad, y mi año tiene 365 días.

Los resultados son diferentes en Linux y Windows.

Para sacar la conclusión correcta, debo mencionar que mi PC con Linux funciona durante aproximadamente 5 horas (305 minutos) y mi PC con Windows durante más de 6 horas (391 minutos).

std::chrono::system_clock y std::chrono::high_solution_clock tienen en Linux la época UNIX como punto de partida. El punto de partida de std::chrono::steady_clock es el tiempo de arranque de mi PC. La diferencia entre Linux y Windows es std::high_solution_clock. En Linux, el std::chrono::system_clock se usa internamente; en Windows, el std::chrono::steady_clock se usa internamente.

¿Qué sigue?

Ese no es el final de la historia sobre la nueva biblioteca del tiempo. Con el punto de tiempo y la duración del componente, puede poner un hilo para un tiempo absoluto o relativo para dormir. Los detalles seguirán en la próxima publicación.