2017-09-21 9 views
1

J'ai une fonction que je veux appeler, disons, 10 fois par seconde. Je commence avec le code comme ceci:Comment effectuer une opération qui prend un certain temps tout en maintenant un débit moyen donné

while True: 
    the_operation() 
    time.sleep(1.0/TIMES_PER_SECOND) 

Cela fonctionne bien, mais the_operation est appelé un peu moins souvent que souhaité, en raison du temps de faire l'opération elle-même. Nous pouvons faire le look de code comme ceci:

while True: 
    t = time.time() 
    the_operation() 
    time_to_sleep = 1.0/TIMES_PER_SECOND - (time.time() - t) 
    if time_to_sleep > 0: 
     time.sleep(time_to_sleep) 

C'est mieux, mais pas encore assez bon - le temps d'exécuter la boucle est pas considéré, et si the_operation arrive à prendre beaucoup plus longtemps que 1/TIMES_PER_SECOND en une seule itération, notre débit sera trop faible. L'opération prend en moyenne moins de 1/TIMES_PER_SECOND, mais le code doit gérer les cas où cela prend plus de temps.

Quel est un bon motif pour appeler the_operation au taux spécifié en moyenne?

Répondre

0

Gardez une trace de l'heure à laquelle vous vous attendez à voir si les opérations sont effectuées au bon débit. Cela vous permettra de comparer l'heure réelle avec l'heure désirée, et vous pouvez dormir pour la différence si elle est positive. Si c'est négatif, les opérations seront exécutées en continu sans sommeil jusqu'à ce que nous rattrapons.

expected = time.monotonic() 
while True: 
    the_operation() 
    expected += 1.0/TIMES_PER_SECOND 
    time.sleep(max(0, expected - time.monotonic())) 

Cela fonctionne même si un retard se produit à tout moment dans la boucle (par exemple le système d'exploitation décidé de ne pas planifier notre processus).

time.monotonic() doit être utilisé au lieu de time.time() parce que ce dernier est soumis à des ajustements de temps, alors que monotonic() toujours augmente de façon monotone à un taux constant, même lorsque l'horloge système est réglé.

Il peut être utile d'être averti si les opérations sont trop lentes et que nous ne pouvons pas atteindre le débit souhaité. Nous pouvons remplacer la construction sleep/max par quelque chose comme ceci:

adjust = expected - time.monotonic() 
if adjust > 0: 
    time.sleep(adjust) 
elif adjust < -10: 
    print("Can't keep up!", -adjust, "seconds behind.")