112 votes

Quelle est la précision de la fonction time.sleep() de Python ?

Je peux lui donner des nombres à virgule flottante, tels que

time.sleep(0.5)

mais quelle est sa précision ? Si je lui donne

time.sleep(0.05)

Est-ce que ça va vraiment dormir à 50 ms ?

92voto

Joe Points 1396

La précision de la fonction time.sleep dépend de la précision du sommeil de votre système d'exploitation sous-jacent. Pour les systèmes d'exploitation non temps réel comme le Windows standard, le plus petit intervalle de sommeil possible est d'environ 10-13 ms. J'ai vu des endormissements précis à quelques millisecondes de ce temps lorsqu'ils étaient supérieurs au minimum de 10-13ms.

Mise à jour : Comme mentionné dans les documents cités ci-dessous, il est courant de faire le sommeil dans une boucle qui s'assurera de se rendormir si elle vous réveille tôt.

Je dois également mentionner que si vous utilisez Ubuntu, vous pouvez essayer un noyau pseudo-temps réel (avec le patch RT_PREEMPT) en installant le paquet rt kernel (au moins dans Ubuntu 10.04 LTS).

EDIT : Les noyaux Linux non temps réel ont un intervalle de sommeil minimum beaucoup plus proche de 1ms que de 10ms mais il varie de manière non déterministe.

11 votes

En fait, les noyaux Linux ont adopté par défaut un taux de tic-tac plus élevé depuis un certain temps, de sorte que le sommeil "minimum" est beaucoup plus proche de 1ms que de 10ms. Ce n'est pas garanti - une autre activité du système peut empêcher le noyau de programmer votre processus aussi rapidement que vous le souhaiteriez, même sans contention du CPU. C'est ce que les noyaux en temps réel essaient de résoudre, je pense. Mais, à moins que vous n'ayez vraiment besoin d'un comportement en temps réel, le simple fait d'utiliser un taux de tic élevé (paramètre HZ du noyau) vous permettra d'obtenir des sleeps non garantis mais à haute résolution sous Linux sans utiliser quoi que ce soit de spécial.

1 votes

Oui, vous avez raison, j'ai essayé avec Linux 2.6.24-24 et j'ai pu obtenir des taux de mise à jour assez proches de 1000 Hz. Au moment où je faisais cela, j'exécutais aussi le code sur Mac et Windows, donc j'ai probablement confondu. Je sais que Windows XP au moins a une fréquence de tic-tac d'environ 10ms.

0 votes

Sous Windows 8, j'obtiens un peu moins de 2 ms

76voto

Wilbert Points 191

Les gens ont tout à fait raison au sujet des différences entre les systèmes d'exploitation et les noyaux, mais je ne vois aucune granularité dans Ubuntu et je vois une granularité de 1 ms dans MS7. Ce qui suggère une implémentation différente de time.sleep, pas seulement un taux de tic différent. Une inspection plus attentive suggère une granularité de 1μs dans Ubuntu d'ailleurs, mais cela est dû à la fonction time.time que j'utilise pour mesurer la précision. Linux and Windows typical time.sleep behaviour in Python

13 votes

Il est intéressant de voir comment Linux a choisi de toujours dormir un peu plus longtemps que prévu, alors que Microsoft a choisi l'approche inverse.

3 votes

@jleahy - L'approche de Linux me semble logique : le sommeil est en fait une libération de la priorité d'exécution pendant un certain temps, après quoi vous vous soumettez à nouveau à la volonté de l'ordonnanceur (qui peut ou non vous programmer pour une exécution immédiate).

0 votes

Sous Windows 8, je ne vois pas Windows dormir moins longtemps que le temps demandé. Je suis également capable de dormir moins de 1ms mais n'importe où en dessous de 1ms j'obtiens 0.00009ms ! (peut-être ne dort-il pas du tout)

28voto

Stephan202 Points 27707

De la documentation :

En revanche, la précision de time() y sleep() est meilleur que leurs équivalents Unix : les temps sont exprimés sous forme de nombres à virgule flottante, time() renvoie l'heure la plus précise disponible (sous Unix gettimeofday si disponible), et sleep() sera acceptera un temps avec une fraction non nulle (Unix select est utilisé pour mettre en œuvre pour la mettre en œuvre, lorsqu'elle est disponible).

Et plus spécifiquement w.r.t. sleep() :

Suspendre l'exécution pour le nombre donné de secondes. L'argument peut être un nombre à virgule flottante pour indiquer un pour indiquer un temps de sommeil plus précis. Le temps réel de temps de suspension peut être moins que celle demandé car tout signal capté mettra fin à la sleep() suivant l'exécution de la routine de capture de ce signal de ce signal. De même, le temps de suspension peut être plus longue que demandé par un d'un montant arbitraire en raison de la l'ordonnancement d'autres activités dans le système.

2 votes

Quelqu'un peut-il expliquer le "parce que tout signal capté mettra fin au sleep() suivant l'exécution de la routine de capture de ce signal" ? À quels signaux fait-il référence ? Merci !

2 votes

Les signaux sont comme des notifications que le système d'exploitation gère ( fr.wikipedia.org/wiki/Unix_signal ), cela signifie que si le système d'exploitation a reçu un signal, la fonction sleep() est terminée après avoir traité ce signal.

18voto

Ants Aasma Points 22921

Pourquoi ne pas le découvrir :

from datetime import datetime
import time

def check_sleep(amount):
    start = datetime.now()
    time.sleep(amount)
    end = datetime.now()
    delta = end-start
    return delta.seconds + delta.microseconds/1000000.

error = sum(abs(check_sleep(0.050)-0.050) for i in xrange(100))*10
print "Average error is %0.2fms" % error

Pour mémoire, j'obtiens environ 0,1 ms d'erreur sur mon HTPC et 2 ms sur mon ordinateur portable, tous deux sous Linux.

13 votes

Les tests empiriques vous donneront une vue très étroite. Il existe de nombreux noyaux, systèmes d'exploitation et configurations de noyaux qui affectent cet aspect. Les noyaux Linux plus anciens utilisent par défaut un taux de tic-tac plus faible, ce qui donne une plus grande granularité. Dans l'implémentation Unix, un signal externe pendant le sommeil l'annulera à tout moment, et d'autres implémentations pourraient avoir des interruptions similaires.

6 votes

Bien sûr, l'observation empirique n'est pas transférable. En dehors des systèmes d'exploitation et des noyaux, il y a beaucoup de problèmes transitoires qui affectent cette situation. Si des garanties de temps réel sont requises, il faut prendre en considération la conception du système dans son ensemble, depuis le matériel jusqu'à l'ordinateur. J'ai juste trouvé les résultats pertinents compte tenu des déclarations selon lesquelles 10 ms est la précision minimale. Je ne suis pas à l'aise dans le monde de Windows, mais la plupart des distros linux utilisent des noyaux sans tic depuis un moment maintenant. Avec la prédominance des multicores, il est très probable que la programmation soit très proche du délai d'attente.

3voto

Nick Bastin Points 12627

Vous ne pouvez pas vraiment garantir quoi que ce soit à propos de sleep(), sauf qu'il fera au moins un effort pour dormir aussi longtemps que vous le lui demandez (des signaux peuvent tuer votre sommeil avant la fin du temps imparti, et beaucoup d'autres choses peuvent le faire durer).

Il est certain que le minimum que vous pouvez obtenir sur un système d'exploitation de bureau standard sera d'environ 16 ms (granularité de la minuterie plus le temps de changement de contexte), mais il y a de fortes chances que l'écart en % par rapport à l'argument fourni soit significatif lorsque vous essayez de dormir pendant des dizaines de millisecondes.

Les signaux, les autres threads qui détiennent la GIL, les plaisirs de l'ordonnancement du noyau, les variations de la vitesse du processeur, etc. peuvent tous avoir un impact sur la durée du sommeil de votre thread/processus.

3 votes

La documentation dit le contraire : > Le temps de suspension réel peut être inférieur à celui demandé car tout signal capturé mettra fin à la sleep() suivant l'exécution de la routine de capture de ce signal.

0 votes

Ah, c'est vrai, j'ai corrigé le message, bien qu'obtenir des sleeps() plus longs soit beaucoup plus probable que des plus courts.

1 votes

Deux ans et demi plus tard ... la documentation ment toujours. Sous Windows, les signaux ne terminent pas sleep(). Testé sur Python 3.2, WinXP SP3.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X