Altenwald Blog
Blog sobre programación, software libre, redes, servidores, ...
Menú
Acerca de... ¿Quiénes somos? RSS
Categorías
sistemas (70) desarrollo (128) historias (25) productividad (49) seguridad (10) libros (25) noticias (45) opinión (35) humor (3)
Etiquetas
programación (111) desarrollo de software (79) erlang (75) opinión (37) noticia (36) libros (28) servidores (26) desarrollo web (24) base de datos (24) administración de sistemas (23) php (22) desarrollo ágil (22) empresa (21) otp (20) ruby (19) ingeniería de negocio (18) elixir (18) desarrollo profesional (16) redes (16) seguridad (14)
2015-12-19
6 min sistemas
La Hora en Erlang
[ erlang ]  [ hora ] 

Cuando hablamos de Erlang y enumeramos sus características entre ellas aparece el tiempo real blando (soft realtime). Erlang se ejecuta en una máquina virtual que tiene una gestión de procesos, memoria y acceso a recursos, pero lo que no había citado hasta el momento es su capacidad para controlar los eventos horarios. Sí, tiene gestión horaria dentro de su máquina virtual también, ¿para qué?, ¿cómo funciona?

Desde el principio: Tiempo monótono.

El tiempo real de un ordenador se ve modificado constantemente, se reajusta saltando hacia adelante o a veces hacia atrás para obtener siempre la hora del día. Incluso si empleamos técnicas como el uso de un cliente NTP, este cliente puede ajustar el reloj local para ajustarlo a la hora "real" medida con precisión por otro sistema.

Si necesitamos que un evento en el tiempo tarde un tiempo específico o tenga un tiempo de duración máxima (timeout), necesitamos que el tiempo se mantenga constante, avanzando siempre y con la misma velocidad a ser posible. Decimos que necesitamos una medición de tiempo monótona (en ingles monotonic time).

Además, podemos decir que un sistema emplea un tiempo monótono estricto únicamente si siempre que es llamado nos proporciona un valor diferente y ascendente con respecto al anterior. En Erlang, hasta la versión 18 hemos podido emplear erlang:now/0 como una marca de tiempo monótona estricta. Pero esto tiene un alto coste.

Debido al coste computacional de erlang:now/0, en la versión 18 se introducen un nuevo conjunto de funciones de tiempo. Esta vez empleando tiempo monótono no estricto, es decir, el tiempo puede retornar valores repetidos pero nunca ir hacia atrás.

Esta nueva forma de obtener el tiempo ha hecho posible incrementar el rendimiento de temporizadores (timers) y gestión de eventos.

La hora de Erlang y la hora del sistema operativo

Para que el sistema sea fiable finalmente debe mantener la hora dentro de la máquina virtual, la hora monótona, y poder proporcionar la hora del sistema operativo. Esto lo conseguimos con las siguientes funciones:

La hora del sistema operativo se puede obtener en el formato antiguo de {MegaSec,Sec,MicroSec} con la función os:timestamp/0, la equivalente en este mismo formato para obtener la hora de Erlang era anteriormente erlang:now/0. A partir de la versión 18 es más aconsejable emplear erlang:timestamp/0.

¿Cómo era antes de la versión 18?

La hora monótona estricta se obtenía con erlang:now/0 tal y como he mencionado antes, pero esto tiene varios problemas, el más significativo es el cuello de botella que puede suponer si es empleada de forma constante y en realidad no se necesita un tiempo monótono estricto, sino tan solo uno monótono. Siempre cabe la posibilidad de emplear os:timestamp/0, pero esta función no retorna valores monótonos.

Además, el reloj interno de la máquina virtual de Erlang tiende a compensarse incrementando o decrementando su frecuencia de actualización para adaptarse paulatinamente al reloj del sistema.

Este comportamiento puede ser contraproducente si nuestro sistema depende del disparo de eventos basados en tiempo a lo largo del cluster debido a que el sistema lanzará los eventos con un poco de mayor o menor frecuencia que el resto de nodos del cluster, según sea el caso.

Para evitar este comportamiento siempre podemos emplear la optión +c que deshabilita este ajuste de hora.

¿Y ahora en la versión 18?

Las funcionalidades de erlang:now/0 se han partido en varias funciones:

Así mismo, la opción de la máquina virtual +c ha adoptado varias opciones posibles, según el tipo de túnel del tiempo que queramos usar.

Túneles del tiempo... ¿qué son?

Básicamente es la configuración del desplazamiento que se configurará para ajustar el reloj de la máquina virtual de Erlang con la hora del sistema cada vez que haya un cambio de hora en el sistema.

Tenemos varias configuraciones posibles que se ajustan con la opción +C. Entre ellas (tomado de las definiciones del libro Learn You Some Erlang...):

En el caso de single_time_warp se puede llamar a erlang:system_flag(time_offset, finalize) para indicar al sistema que puede tomar el offset en ese momento. Es útil para sistemas embebidos donde se emplea el ajuste del reloj solo al inicio del sistema y podemos o queremos ajustar el reloj tras este ajuste.

De todas formas, por la complejidad del ajuste, se recomienda mantener el código seguro o emplear en su lugar siempre no_time_warp.

¿Cómo mantener el código seguro?

La documentación de Erlang nos dicen cómo mantener el código seguro en estos casos y en el libro Learn You Some Erlang... nos sintetizan esta información en unos sencillos puntos a seguir cuando queramos utilizar el tiempo, ya sea por eventos o por el uso de fechas y horas:

Siguiendo estas guías, el código debe mantenerse seguro respecto a los túneles de tiempo.

Autor
Manuel Rubio
Programación Concurrente & Erlanger