[EDIT] Une réécriture majeure avec des références car je viens de noter l'ancienne réponse de mémoire.
Réponse courte :non. Il n'est pas possible d'obtenir une précision proche de la milliseconde à partir d'un système d'exploitation ordinaire sur une plate-forme x86/x64 aujourd'hui.
AVIS DE NON-RESPONSABILITÉ Ceci est une réponse pour les profanes car je suis un administrateur système ordinaire avec une vue ordinaire des administrateurs système sur les ordinateurs. Un niveau professionnel de connaissance du chronométrage se trouve probablement chez certains développeurs de noyau et architectes matériels.
Réponse longue :
Il faut commencer quelque part. Je vais le faire de haut en bas, en commençant par les applications descendant vers le ou les oscillateurs.
Le premier problème n'est pas d'avoir le chronométrage sur un seul ordinateur, mais de réussir à faire en sorte que l'environnement dans son ensemble s'accorde sur le chronométrage dont vous disposez. Quel chronométrage ? Il s'avère qu'il existe plusieurs façons de conserver l'heure dans un ordinateur d'aujourd'hui. Celui que nous voyons le plus est l'heure système (telle qu'affichée dans l'un des coins de l'écran). Commençons par prétendre que c'est aussi simple et compliquons les choses quelques paragraphes plus bas.
Nous voulons que l'heure du système soit correcte et nous voulons qu'elle soit uniforme sur tous nos ordinateurs. Nous avons besoin d'un moyen de le communiquer à partir d'une source fiable à un niveau si granulaire afin de répondre à nos exigences, quelles qu'elles soient.
Faisons de notre exigence un niveau de tolérance de 1 ms, c'est-à-dire que notre temps peut dévier de 1 ms dans notre environnement ou nous manquons un objectif critique. Soyons concrets et voyons ce que Microsoft peut faire pour nous.
À l'exclusion des obsolètes tels que NT, Windows natif exécute son chronométrage sur la base soit de ntp simplifié (ordinateurs joints à un domaine commençant par XP/2003) soit de sntp simplifié (ordinateurs non joints à un domaine commençant par Win2k) - merci à @Ryan d'avoir pointillé ce détail . Lors de la mise en œuvre du chronométrage, Microsoft s'est fixé deux objectifs, dont aucun n'inclut le niveau de précision souhaité :
"Nous ne garantissons pas et nous ne prenons pas en charge la précision du service W32Time entre les nœuds d'un réseau. Le service W32Time n'est pas une solution NTP complète qui répond aux besoins des applications sensibles au facteur temps. Le service W32Time est principalement conçu pour faire ce qui suit :
- Faire fonctionner le protocole d'authentification Kerberos version 5.
- Fournit un temps de synchronisation lâche pour les ordinateurs clients.
Le service W32Time ne peut pas maintenir de manière fiable l'heure de synchronisation dans une plage d'une à deux secondes. De telles tolérances sont en dehors des spécifications de conception du service W32Time."
D'ACCORD. En supposant que nous exécutons votre pile de services sur plusieurs ordinateurs et que nous ayons un niveau de tolérance de chronométrage approchant 1 ms pour la corrélation des événements, c'est assez décevant. Si la pile de services comprend deux ordinateurs, nous ne pouvons en fait pas du tout utiliser le chronométrage natif de Windows. Mais pendant que nous y sommes, soulignons un point clé ou deux sur le chronométrage natif de Windows, et incluons une documentation complète :
Si vous avez un AD, observez que l'heure dans un domaine donné sera synchronisée à partir du rôle d'émulateur PDC, quel que soit le DC qui l'a. L'introduction de l'heure correcte dans le domaine doit donc se faire via le contrôleur de domaine exécutant le rôle d'émulateur PDC. Si dans une forêt multidomaine, cela se traduit par l'émulateur PDC du domaine racine de la forêt. À partir de là, le temps est principalement distribué aux émulateurs PDC des sous-domaines et à chaque membre du domaine en éventail (avec quelques mises en garde). Ce processus est documenté ici. Des informations encore plus détaillées ici
D'ACCORD. Que pouvons-nous faire ?
Pour commencer, nous avons besoin d'un moyen plus précis de synchroniser le temps dans tout l'environnement. En supposant que nous ne puissions pas exécuter Linux ntpd ou ntpd pour Windows, vous pouvez jeter un œil à un client shareware appelé Tardis, mais il y en a probablement beaucoup d'autres à essayer.
Nous avons exécuté Tardis sur un serveur Win2k3 fonctionnant en tant qu'émulateur PDC qui avait une horloge CMOS avec un très grand décalage, pour des raisons historiques inexplicables, nous n'avions pas d'autre choix que de synchroniser l'ensemble du réseau à partir de celui-ci. Maintenant, il a été remplacé avec une grande joie par un ntpd Linux dédié apportant du temps à partir d'horloges atomiques à l'extérieur, mais Tardis nous a admirablement sauvés sur-le-champ. Je ne sais pas cependant si cela pourrait vous aider à atteindre une précision supérieure à celle de Windows natif.
Mais supposons à partir de maintenant que nous avons trouvé comment implémenter une parfaite synchronisation de l'heure du réseau de substitution. Grâce à sa ruse inhérente, il a une capacité pour des niveaux de tolérance inférieurs à une milliseconde. Nous l'avons mis en place afin d'appliquer la façon dont notre AD s'attend à ce que le temps se propage sur le réseau.
Cela signifie-t-il que nous pouvons obtenir des diagnostics précis des systèmes d'exploitation et des microservices à une granularité proche de la milliseconde ?
Regardons comment les systèmes d'exploitation sur l'architecture x86/x64 planifient le temps processeur.
Ils utilisent des interruptions, qui sont des bêtes à multiples facettes riches en substance archéologique. Cependant, le système d'exploitation n'est pas le seul à vouloir interrompre. Le matériel souhaite lui aussi interrompre, et il a les moyens de le faire ! (Bonjour clavier) Et les systèmes d'exploitation jouent le jeu.
C'est là que ça se complique et je vais résoudre ce problème en simplifiant à l'excès. Des questions? Je me penche, je couvre et vous indique un traité absolument excellent sur le sujet. (Si vous recherchez des millisecondes sur une plate-forme Windows, vous devriez vraiment le lire.) Une version mise à jour pour Win8.1/Win2012r2 serait en préparation, mais aucune date de sortie n'a encore fait surface.
OK, interrompt. Chaque fois que quelque chose doit se produire dans un système d'exploitation, une interruption déclenche l'action qui suit. L'action est un ensemble d'instructions extraites du noyau, qui peuvent être exécutées de différentes manières. L'essentiel est que, bien que l'interruption se produise à un moment qui peut être déterminé avec plus ou moins de précision en fonction de l'architecture matérielle et de la gestion des interruptions du noyau, l'heure exacte à laquelle les parties suivantes de l'exécution se produisent généralement ne peut pas. Un ensemble spécifique d'instructions peut être exécuté tôt après l'interruption ou tardivement, il peut être exécuté dans une séquence prévisible ou non, il peut être victime d'un matériel bogué ou de pilotes mal écrits affectant des latences difficiles à reconnaître. La plupart du temps, on ne sait tout simplement pas. L'horodatage au niveau de la milliseconde qui s'affiche dans le fichier journal suivant :il est très précis, mais est-il précis quant au moment où l'événement s'est produit ?
Arrêtons-nous brièvement sur l'interruption de chronométrage. Une interruption est associée à un niveau de priorité, le niveau le plus bas étant celui où les applications utilisateur (comme un service standard) obtiennent leur temps processeur. Les autres niveaux (supérieurs) sont réservés au matériel et au travail du noyau. Si une interruption à un niveau supérieur au plus bas arrive, le système prétendra que les interruptions de priorité inférieure également dans la file d'attente n'existent pas (jusqu'à ce que les interruptions de priorité supérieure aient été prises en charge). Les applications et services ordinaires en cours d'exécution seront ainsi les derniers en ligne pour le temps processeur. En revanche, la priorité presque la plus élevée est donnée à l'interruption d'horloge. La mise à jour de l'heure sera presque toujours effectuée dans un système. Il s'agit d'une simplification presque criminelle de la façon dont tout cela fonctionne, mais cela sert le but de cette réponse.
Le temps de mise à jour consiste en fait en deux tâches :
-
Mise à jour de l'heure du système / AKA l'horloge murale / AKA ce que je dis quand quelqu'un me demande quelle heure il est / AKA la chose ntp bricole un peu d'avant en arrière par rapport aux systèmes à proximité.
-
Mise à jour du nombre de ticks, utilisé par exemple lors de la mesure des durées d'exécution du code.
Mais qu'il s'agisse de l'heure du mur ou du nombre de ticks, d'où le système tire-t-il l'heure ? Cela dépend beaucoup de l'architecture matérielle. Quelque part dans le matériel, un ou plusieurs oscillateurs fonctionnent, et ce tic-tac est amené via l'un des nombreux chemins possibles dans une interface de contact avec le noyau, car il met à jour avec une précision et une exactitude plus ou moins grandes son temps de mur et son nombre de tic.
Il existe plusieurs modèles de conception pour le placement de l'oscillateur dans un système multicœur, le principal différenciateur semble être le placement synchrone par rapport au placement asynchrone. Ceux-ci ainsi que leurs défis respectifs pour un chronométrage précis sont décrits ici par exemple.
En bref, le chronométrage synchrone a une horloge de référence par multicœur, qui reçoit son signal distribué à tous les cœurs. Le chronométrage asynchrone a un oscillateur par cœur. Il est à noter que les derniers processeurs multicœurs Intel (Haswell) utilisent une forme de conception synchrone utilisant un bus série appelé "QuickPath Interconnect" avec "Forwarded Clocking", réf. Fiche de données. Le Forwarded Clocking est décrit dans des termes tels qu'un profane (moi) peut en avoir une compréhension superficielle rapide ici.
OK, donc avec tout ce nerderism à l'écart (qui a servi à montrer que le chronométrage est une tâche pratique complexe avec beaucoup d'histoire vivante à ce sujet), regardons encore plus près la gestion des interruptions.
Les systèmes d'exploitation gèrent les interruptions en utilisant l'une des deux stratégies distinctes :ticking ou tickless. Vos systèmes utilisent l'un ou l'autre, mais que signifient ces termes ?
Noyaux à cocher envoyer des interruptions à intervalles fixes. Le système d'exploitation ne peut pas mesurer le temps à une résolution plus fine que l'intervalle de tic. Même dans ce cas, le traitement réel impliqué dans l'exécution d'une ou plusieurs actions peut très bien contenir un retard supérieur à l'intervalle de tic. Considérons par exemple les systèmes distribués (tels que les microservices) où les retards inhérents aux appels interservices peuvent consommer relativement beaucoup de temps. Pourtant, chaque ensemble d'instructions sera associé à une ou plusieurs interruptions mesurées par le système d'exploitation à une résolution pas plus fine que le temps de tic-tac du noyau. Le temps de tic a une valeur de base mais peut au moins sous Windows être diminué à la demande par une application individuelle. Il s'agit d'une action associée non seulement à des avantages, mais également à des coûts, et comporte pas mal de petits caractères.
Soi-disant noyaux sans chatouilles (qui ont un nom très peu descriptif) sont une invention relativement nouvelle. Un noyau sans tick définit le temps de tick à des intervalles variables (durée aussi longue que possible dans le futur). La raison en est que le système d'exploitation permet dynamiquement aux cœurs de processeur de passer à différents niveaux de sommeil aussi longtemps que possible, dans le simple but d'économiser de l'énergie. Les "différents niveaux" incluent le traitement des instructions à pleine vitesse, le traitement à des vitesses réduites (c'est-à-dire une vitesse de processeur plus lente) ou l'absence de traitement du tout. Différents cœurs sont autorisés à fonctionner à des rythmes différents et le noyau instable essaie de laisser les processeurs être aussi inactifs que possible, même dans les cas où la mise en file d'attente d'instructions pour les déclencher par lots d'interruptions. En bref, différents cœurs d'un système multiprocesseur peuvent dériver dans le temps les uns par rapport aux autres. Bien sûr, cela nuit à la bonne tenue du temps et constitue jusqu'à présent un problème non résolu avec les nouvelles architectures de processeur à économie d'énergie et les noyaux instables qui leur permettent de réaliser des économies d'énergie efficaces. Comparez cela avec un noyau de ticking (intervalle de tick statique) qui réveille continuellement tous les cœurs de processeur, qu'ils reçoivent ou non du travail réel, et où le chronométrage comporte un certain degré d'imprécision mais à un degré relativement fiable par rapport aux noyaux tickless.
Le temps de tic standard de Windows - c'est-à-dire la résolution du système - est de 15,6 ms jusqu'à Windows 8/2012 où le comportement par défaut est sans tick (mais est réversible au noyau ticking). Je pense que le temps de tic par défaut de Linux dépend de la compilation du noyau, mais ce créneau est bien en dehors de mon expérience (et celui-ci aussi), vous pouvez donc vérifier si vous en dépendez. Je crois que les noyaux Linux sont compilés tickless à partir du 2.6.21 et peuvent être compilés avec divers drapeaux optimisant le comportement tickless (et dont je ne me souviens que de quelques variantes de no_hz).
Voilà pour les systèmes en métal nu. Dans les systèmes virtuels, la situation s'aggrave, car les conflits de VM et d'hyperviseur de différentes manières rendent le chronométrage précis extrêmement difficile. Voici un aperçu pour VMware et en voici un pour RHEL KVM. Il en va de même pour les systèmes distribués. Les systèmes cloud sont encore plus difficiles car nous ne sommes même pas près de voir des hyperviseurs et du matériel réels.
Pour conclure, obtenir une heure précise d'un système est un problème à plusieurs niveaux. En allant maintenant de bas en haut d'un point de vue de haut niveau, nous devons résoudre :la synchronisation temporelle interne entre le matériel et le noyau, le traitement des interruptions et les retards dans l'exécution des instructions dont nous souhaitons l'heure, si dans un environnement virtuel des inexactitudes grâce à l'encapsulation d'une deuxième couche OS, la synchronisation de l'heure entre les systèmes distribués.
Par conséquent, à ce stade de l'histoire de l'informatique, nous n'obtiendrons pas une précision de niveau milliseconde avec une architecture x86/x64, du moins sans utiliser aucun des systèmes d'exploitation courants.
Mais jusqu'où peut-on s'en approcher ? Je ne sais pas et cela devrait varier considérablement d'un système à l'autre. Maîtriser l'inexactitude de ses propres systèmes spécifiques est une tâche ardue. Il suffit de regarder comment Intel suggère que l'analyse comparative du code soit effectuée pour voir que les systèmes ordinaires, tels que ceux que j'administre, sont totalement incontrôlables dans cette perspective.
Je n'envisage même pas d'atteindre "Toutes les fonctionnalités d'optimisation de la puissance, de technologie Intel Hyper-Threading, de mise à l'échelle de fréquence et de mode turbo ont été désactivées" dans les systèmes critiques, beaucoup moins de bricolage avec les wrappers de code en C et l'exécution de tests à long terme pour obtenir des réponses ultérieures. J'essaie juste de les garder en vie et d'en apprendre le plus possible sur eux sans trop les déranger. Merci l'horodatage, je sais que je ne peux pas te faire entièrement confiance mais je sais que tu n'es pas trop loin. Lorsque la précision réelle à la milliseconde devient importante, une mesure ne suffit pas, mais un plus grand nombre de mesures est nécessaire pour vérifier le modèle. Que pouvons-nous faire d'autre ?
Enfin, il est intéressant de voir comment les gens du système d'exploitation en temps réel pensent la latence d'interruption. Il existe également une alternative de synchronisation temporelle très excitante dans les travaux, où un certain nombre de statistiques, de méthodologies et de livres blancs intéressants sont rendus publics. Ajoutez à cela l'architecture matérielle future et les développements du noyau et dans quelques années, cette précision de chronométrage ne sera peut-être plus un problème. On peut espérer.