[EDITAR] Una reescritura importante con referencias, ya que acabo de anotar la respuesta anterior de memoria.
Respuesta corta:no. Actualmente, no es posible obtener una precisión de casi milisegundos con un sistema operativo corriente en una plataforma x86/x64.
DESCARGO DE RESPONSABILIDAD Esta es una respuesta para profanos, ya que soy un administrador de sistemas ordinario con una visión ordinaria de los administradores de sistemas de las computadoras. Es probable que algunos desarrolladores de kernel y arquitectos de hardware tengan un nivel profesional de conocimiento del cronometraje.
Respuesta larga:
Uno tiene que empezar en alguna parte. Lo haré de arriba hacia abajo, comenzando con las aplicaciones moviéndose hacia el oscilador(es).
El primer problema no es tener el cronometraje en una computadora, sino lograr que el entorno en su conjunto esté de acuerdo con cualquier cronometraje que tenga. ¿Qué cronometraje? Resulta que hay un par de formas de mantener el tiempo en una computadora de hoy. La que más vemos es la hora del sistema (como se muestra en una de las esquinas de las pantallas). Comencemos fingiendo que es así de simple y compliquemos las cosas un par de párrafos más abajo.
Queremos que la hora del sistema sea correcta y queremos que sea uniforme en todas nuestras computadoras. Necesitamos una forma de comunicarlo desde una fuente confiable a un nivel tan granular como para cumplir con nuestros requisitos, sean cuales sean.
Hagamos nuestro requerimiento en un nivel de tolerancia de 1 ms, es decir, nuestro tiempo puede desviarse 1 ms dentro de nuestro entorno o perdemos una meta crítica. Seamos concretos y veamos qué puede hacer Microsoft por nosotros.
Excluyendo los obsoletos como NT, Windows nativo ejecuta su cronometraje basado en ntp simplificado (computadoras unidas a un dominio que comienzan con XP/2003) o sntp simplificado (computadoras no unidas a un dominio que comienzan con Win2k) - gracias a @Ryan por ser quisquilloso con este detalle . Microsoft estableció dos objetivos al realizar la implementación del cronometraje, ninguno de los cuales incluye nuestro nivel deseado de precisión:
"No garantizamos ni respaldamos la precisión del servicio W32Time entre los nodos de una red. El servicio W32Time no es una solución NTP con funciones completas que satisfaga las necesidades de las aplicaciones sensibles al tiempo. El servicio W32Time está diseñado principalmente para hacer lo siguiente:
- Haga que funcione el protocolo de autenticación Kerberos versión 5.
- Proporcione tiempo de sincronización flexible para los equipos cliente.
El servicio W32Time no puede mantener de manera confiable el tiempo de sincronización en el rango de uno a dos segundos. Dichas tolerancias están fuera de la especificación de diseño del servicio W32Time".
ESTÁ BIEN. Suponiendo que estamos ejecutando su pila de servicios en más de una computadora y tenemos un nivel de tolerancia de cronometraje cercano a 1 ms para la correlación de eventos, eso es una gran decepción. Si la pila de servicios incluye dos computadoras, en realidad no podemos usar el cronometraje nativo de Windows en absoluto. Pero mientras estamos en eso, subrayemos uno o dos puntos clave sobre el cronometraje nativo de Windows e incluyamos documentación detallada:
Si tiene un AD, observe que la hora en un dominio determinado se sincronizará desde el rol de Emulador de PDC, cualquiera que sea el DC que lo tenga. Por lo tanto, la hora correcta en el dominio debe realizarse a través del controlador de dominio que ejecuta la función de emulador de PDC. Si está en un bosque de varios dominios, esto se traduce en el emulador de PDC del dominio raíz del bosque. A partir de ahí, el tiempo se distribuye principalmente en los emuladores de PDC de los subdominios y en cada miembro del dominio en forma de abanico (con algunas advertencias). Este proceso está documentado aquí. Información aún más detallada aquí
ESTÁ BIEN. ¿Qué podemos hacer?
Para empezar, necesitamos una u otra forma más precisa de sincronizar el tiempo en todo el entorno. Suponiendo que no podamos ejecutar Linux ntpd o ntpd para Windows, podría echar un vistazo a un cliente shareware llamado Tardis, pero es probable que haya muchos más para probar.
Ejecutamos Tardis en un servidor Win2k3 que funcionaba como PDC Emulator que tenía un reloj CMOS con un sesgo realmente grande, por razones históricas inexplicables, no tuvimos más remedio que sincronizar toda la red desde él. Ahora ha sido reemplazado con gran alegría por un ntpd de Linux dedicado que trae la hora de los relojes atómicos en el exterior, pero Tardis nos salvó admirablemente en ese momento. Sin embargo, no sé si podría ayudarlo a lograr una precisión mayor que la nativa de Windows.
Pero supongamos a partir de este momento que hemos descubierto cómo implementar una sincronización de tiempo de red sustituta perfecta. A través de su astucia inherente, tiene una capacidad para niveles de tolerancia por debajo de un milisegundo. Lo hemos implementado para hacer cumplir cómo nuestro AD espera que el tiempo se distribuya a través de la red.
¿Significa esto que podemos obtener diagnósticos precisos de los sistemas operativos y los microservicios con una granularidad cercana a los milisegundos?
Veamos cómo los sistemas operativos en la arquitectura x86/x64 programan el tiempo del procesador.
Utilizan interrupciones, que son bestias multifacéticas ricas en sustancia arqueológica. Sin embargo, el sistema operativo no está solo en su deseo de interrumpir. ¡El hardware también desea interrumpir, y tiene los medios para hacerlo! (Hola teclado) Y los sistemas operativos siguen el juego.
Aquí es donde se complica y lo resolveré simplificando demasiado. ¿Preguntas? Me agacho, cubro y le señalo un tratado absolutamente excelente sobre el tema. (Si está buscando milisegundos en una plataforma Windows, realmente debería leerlo). Según se informa, se está trabajando en una versión actualizada para Win8.1/Win2012r2, pero aún no ha aparecido una fecha de lanzamiento.
Bien, interrumpe. Cada vez que sucede algo en un sistema operativo, una interrupción desencadena la acción que sigue. La acción es un montón de instrucciones extraídas del núcleo, que se pueden ejecutar de muchas maneras diferentes. La conclusión es que, a pesar de que la interrupción ocurre en un momento que se puede determinar con mayor o menor precisión según la arquitectura del hardware y el manejo de la interrupción del kernel, el momento exacto en el que ocurren las partes posteriores de la ejecución generalmente no puede. Un conjunto específico de instrucciones puede ejecutarse temprano después de la interrupción o tarde, puede ejecutarse en una secuencia predecible o no, puede ser víctima de hardware defectuoso o controladores mal escritos que afectan latencias difíciles incluso de reconocer. La mayoría de las veces uno simplemente no sabe. La marca de tiempo de nivel de milisegundos que se muestra en el archivo de registro posterior:es muy precisa, pero ¿es exacta en cuanto a cuándo ocurrió el evento?
Detengámonos brevemente en la interrupción del cronometraje. Una interrupción viene con un nivel de prioridad, el nivel más bajo es donde las aplicaciones de usuario (como un servicio estándar) obtienen su tiempo de procesador. Los otros niveles (superiores) están reservados para el hardware y para el trabajo del kernel. Si llega una interrupción en un nivel superior al más bajo, el sistema pretenderá que no existen interrupciones de prioridad más baja que también estén en la cola (hasta que se hayan atendido las interrupciones de prioridad más alta). Las aplicaciones y los servicios ordinarios que se ejecutan serán, de esta manera, los últimos en tiempo de procesador. Como contraste, casi la prioridad más alta se le da a la interrupción del reloj. La actualización de la hora casi siempre se realizará en un sistema. Esta es una simplificación casi criminal de cómo funciona todo, pero cumple el propósito de esta respuesta.
Actualizar el tiempo en realidad consta de dos tareas:
-
Actualizando la hora del sistema / También conocido como el reloj de pared / También conocido como lo que digo cuando alguien me pregunta qué hora es / También conocido como la cosa ntp juega un poco de un lado a otro en relación con los sistemas cercanos.
-
Actualización del recuento de ticks, que se utiliza, por ejemplo, al medir duraciones en la ejecución del código.
Pero ya sea tiempo de pared o cuenta de ticks, ¿de dónde obtiene el sistema el tiempo? Depende en gran medida de la arquitectura del hardware. En algún lugar del hardware, uno o varios osciladores están haciendo tic-tac, y ese tic-tac se lleva a través de una de varias rutas posibles a una interfaz para contactar con el núcleo, ya que con mayor o menor precisión actualiza su tiempo de pared y cuenta de tic.
Hay varios modelos de diseño para la colocación de osciladores en un sistema multinúcleo, el principal diferenciador parece ser la colocación sincrónica frente a la asincrónica. Estos junto con sus respectivos desafíos para el cronometraje preciso se describen aquí, por ejemplo.
En resumen, el cronometraje síncrono tiene un reloj de referencia por multinúcleo, que distribuye su señal a todos los núcleos. El cronometraje asíncrono tiene un oscilador por núcleo. Vale la pena señalar que los últimos procesadores Intel multinúcleo (Haswell) utilizan alguna forma de diseño síncrono utilizando un bus serie llamado "QuickPath Interconnect" con "Forwarded Clocking", ref. ficha de datos. El reloj reenviado se describe en términos tales que un profano (yo) puede obtener una comprensión rápida y superficial aquí.
OK, así que con todo ese nerdismo fuera del camino (que sirvió para mostrar que el cronometraje es una tarea práctica compleja con mucha historia viva al respecto), veamos aún más de cerca el manejo de interrupciones.
Los sistemas operativos tenían interrupciones utilizando una de dos estrategias distintas:tictac o sin tictac. Sus sistemas usan uno u otro, pero ¿qué significan los términos?
Hacer tictac los núcleos enviar interrupciones a intervalos fijos. El sistema operativo no puede medir el tiempo con una resolución más fina que el intervalo de tictac. Incluso entonces, el procesamiento real involucrado en la realización de una o varias acciones bien puede contener un retraso mayor que el intervalo de tic. Considere, por ejemplo, los sistemas distribuidos (como los microservicios) donde los retrasos inherentes a las llamadas entre servicios podrían consumir relativamente mucho tiempo. Sin embargo, cada conjunto de instrucciones estará asociado con una o varias interrupciones medidas por el sistema operativo a una resolución no más fina que el tiempo de tictac del kernel. El tiempo de marcación tiene un valor base pero, al menos en Windows, puede reducirse a pedido de una aplicación individual. Esta es una acción asociada no solo con los beneficios sino también con los costos, y conlleva bastante letra pequeña.
Los llamados núcleos sin garrapatas (que tienen un nombre muy poco descriptivo) son un invento relativamente nuevo. Un kernel sin ticks establece el tiempo de tick en intervalos variables (la mayor duración posible en el futuro). La razón es que el sistema operativo permite dinámicamente que los núcleos del procesador entren en varios niveles de suspensión durante el mayor tiempo posible, con el simple propósito de conservar energía. Los "varios niveles" incluyen el procesamiento de instrucciones a toda velocidad, el procesamiento a velocidades reducidas (es decir, una velocidad de procesador más lenta) o no procesar en absoluto. Se permite que diferentes núcleos operen a diferentes velocidades y el kernel sin marcas intenta que los procesadores estén lo más inactivos posible, incluso en casos que incluyen instrucciones de cola para dispararlos en lotes de interrupción. En resumen, se permite que diferentes núcleos en un sistema multiprocesador se desvíen en el tiempo entre sí. Esto, por supuesto, causa estragos en el buen mantenimiento del tiempo y, hasta ahora, es un problema sin resolver con las nuevas arquitecturas de procesadores que ahorran energía y los núcleos sin marcas que les permiten ahorrar energía de manera eficiente. Compare esto con un núcleo de tictac (intervalo de tictac estático) que activa continuamente todos los núcleos del procesador, independientemente de que reciban trabajo real o no, y donde el cronometraje conlleva un grado de inexactitud pero en un grado relativamente confiable en comparación con los núcleos sin tictac.
El tiempo de tictac estándar de Windows, es decir, la resolución del sistema, es de 15,6 ms hasta Windows 8/2012, donde el comportamiento predeterminado es sin tictac (pero se puede revertir al kernel de tictac). Creo que el tiempo de marcación predeterminado de Linux depende de la compilación del kernel, pero este nicho está fuera de mi experiencia (y este también), por lo que es posible que desee verificar dos veces si depende de él. Creo que los núcleos de Linux se compilan sin marcas desde 2.6.21 y se pueden compilar con varios indicadores que optimizan el comportamiento sin marcas (y de los cuales solo recuerdo algunas variantes de no_hz).
Hasta aquí los sistemas bare metal. En los sistemas virtuales, la situación empeora, ya que la contienda entre la VM y el hipervisor de diferentes maneras dificulta enormemente el cronometraje preciso. Aquí hay una descripción general de VMware y aquí hay una para RHEL KVM. Lo mismo se aplica a los sistemas distribuidos. Los sistemas en la nube son aún más difíciles, ya que ni siquiera nos acercamos a ver los hipervisores y el hardware reales.
Para concluir, obtener la hora exacta de un sistema es un problema de varias capas. Yendo ahora de abajo hacia arriba desde un punto de vista de alto nivel, tenemos que resolver:Sincronización de tiempo interno entre el hardware y el kernel, procesamiento de interrupciones y retrasos en la ejecución de las instrucciones que deseamos, si en un entorno virtual imprecisiones debido a la encapsulación de una segunda capa del sistema operativo, la sincronización de tiempo entre sistemas distribuidos.
Por lo tanto, en este punto de la historia de la informática, no obtendremos una precisión de milisegundos con una arquitectura x86/x64, al menos sin usar ninguno de los sistemas operativos comunes.
Pero, ¿qué tan cerca podemos llegar? No lo sé y debería variar mucho entre los diferentes sistemas. Controlar la inexactitud de los propios sistemas específicos es una tarea abrumadora. Solo hay que ver cómo Intel sugiere que se debe realizar la evaluación comparativa del código para ver que los sistemas ordinarios, como los que yo administro, están muy fuera de control en esta perspectiva.
Ni siquiera contemplo lograr "Se desactivaron todas las funciones de optimización de energía, tecnología Intel Hyper-Threading, escalado de frecuencia y modo turbo" en sistemas críticos, mucho menos jugar con envolturas de código en C y ejecutar pruebas a largo plazo para obtener respuestas posteriores. Solo trato de mantenerlos con vida y aprender todo lo que puedo sobre ellos sin molestarlos demasiado. Gracias marca de tiempo, sé que no puedo confiar plenamente en ti, pero sé que no te faltan muchos segundos. Cuando la precisión real de milisegundos se vuelve importante, una medida no es suficiente, sino que se necesita una mayor cantidad de medidas para verificar el patrón. ¿Qué más podemos hacer?
Por último, es interesante ver cómo la gente del sistema operativo en tiempo real piensa que interrumpe la latencia. También se está trabajando en una alternativa de sincronización de tiempo muy interesante, en la que se hacen públicas bastantes estadísticas, metodologías e informes técnicos interesantes. Agregue a eso la arquitectura de hardware futura y los desarrollos del kernel y, en unos años, esta cuestión de la precisión del cronometraje puede que ya no sea un problema tan grande. Uno puede esperar.