如何执行耗时的操作同时保持给定的平均吞吐量 [英] How to perform an operation that takes a variable amount of time while maintaining a given average throughput

查看:51
本文介绍了如何执行耗时的操作同时保持给定的平均吞吐量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个要每秒调用10次的函数.我从这样的代码开始:

I have a function that I want to call, say, 10 times per second. I start out with code like this:

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

这可以正常工作,但是由于操作本身需要时间,因此调用__操作的频率比期望的要少一些.我们可以改为使代码看起来像这样:

This works ok but the_operation is called slightly less often than desired, because of the time to do the operation itself. We can make the code look like this instead:

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)

这是更好的方法,但仍然不够好-不考虑执行循环的时间,并且如果一次迭代恰好花费the_operation花费比1/TIMES_PER_SECOND更长的时间,那么我们的吞吐量将太低.该操作平均花费不到1/TIMES_PER_SECOND,但是代码需要处理花费更长时间的情况.

This is better, but still not good enough -- the time to execute the loop is not considered, and if the_operation happens to take significantly longer than 1/TIMES_PER_SECOND in one iteration, our throughput will be too low. The operation on average takes less than 1/TIMES_PER_SECOND, but the code needs to handle the cases where it does take longer.

平均以指定的速率调用the_operation的良好模式是什么?

What is a good pattern for calling the_operation at the specified rate on average?

推荐答案

跟踪您希望看到操作是否以正确速率执行的时间.这样您就可以将实际时间与所需时间进行比较,并且如果正数为正,您可以入睡.如果结果是否定的,那么操作将连续进行,并且不会睡觉,直到我们追上.

Keep track of the time you expect to see if operations are performed at the correct rate. This will let you compare the actual time with the desired time, and you can sleep for the difference if it's positive. If it's negative, the operations will be run continuously with no sleep until we catch up.

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

即使在循环中的任何点发生延迟(例如操作系统决定不安排我们的进程),这也将起作用.

This will work even when a delay happens at any point in the loop (say the operating system decided not to schedule our process).

time.monotonic()代替time.time(),因为后者会进行时间调整,而monotonic()总是单调递增,即使调整了系统时钟也是如此.

time.monotonic() should be used instead of time.time() because the latter is subject to time adjustments, while monotonic() always monotonically increases at a constant rate, even when the system clock is adjusted.

如果操作太慢并且我们无法达到所需的吞吐量,则可能会收到通知.我们可以使用以下方式替换sleep/max构造:

It may be useful to be notified if the operations are too slow and we can't achieve the desired throughput. We can replace the sleep/max construct with something like this:

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

这篇关于如何执行耗时的操作同时保持给定的平均吞吐量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆