如何在保持给定平均吞吐量的同时执行花费可变时间的操作
How to perform an operation that takes a variable amount of time while maintaining a given average throughput
我有一个函数,我想每秒调用 10 次。我从这样的代码开始:
while True:
the_operation()
time.sleep(1.0/TIMES_PER_SECOND)
这工作正常,但 the_operation 的调用频率略低于预期,因为需要时间自行执行操作。我们可以让代码看起来像这样:
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,但代码需要处理花费更长时间的情况。
以指定的平均速率调用 the_operation 的良好模式是什么?
记录您期望的时间,以查看操作是否以正确的速度执行。这将使您可以将实际时间与所需时间进行比较,如果是正数,您可以睡个好觉。如果它是负数,操作将连续 运行 不休眠,直到我们赶上。
expected = time.monotonic()
while True:
the_operation()
expected += 1.0/TIMES_PER_SECOND
time.sleep(max(0, expected - time.monotonic()))
即使在循环中的任何一点发生延迟(假设操作系统决定不安排我们的进程),这也会起作用。
应使用 time.monotonic()
而不是 time.time()
,因为后者受时间调整影响,而 monotonic()
始终以恒定速率单调增加,即使系统时钟已调整.
如果操作速度太慢而我们无法达到所需的吞吐量,那么收到通知可能会很有用。我们可以用这样的东西替换 sleep/max 结构:
adjust = expected - time.monotonic()
if adjust > 0:
time.sleep(adjust)
elif adjust < -10:
print("Can't keep up!", -adjust, "seconds behind.")
我有一个函数,我想每秒调用 10 次。我从这样的代码开始:
while True:
the_operation()
time.sleep(1.0/TIMES_PER_SECOND)
这工作正常,但 the_operation 的调用频率略低于预期,因为需要时间自行执行操作。我们可以让代码看起来像这样:
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,但代码需要处理花费更长时间的情况。
以指定的平均速率调用 the_operation 的良好模式是什么?
记录您期望的时间,以查看操作是否以正确的速度执行。这将使您可以将实际时间与所需时间进行比较,如果是正数,您可以睡个好觉。如果它是负数,操作将连续 运行 不休眠,直到我们赶上。
expected = time.monotonic()
while True:
the_operation()
expected += 1.0/TIMES_PER_SECOND
time.sleep(max(0, expected - time.monotonic()))
即使在循环中的任何一点发生延迟(假设操作系统决定不安排我们的进程),这也会起作用。
应使用time.monotonic()
而不是 time.time()
,因为后者受时间调整影响,而 monotonic()
始终以恒定速率单调增加,即使系统时钟已调整.
如果操作速度太慢而我们无法达到所需的吞吐量,那么收到通知可能会很有用。我们可以用这样的东西替换 sleep/max 结构:
adjust = expected - time.monotonic()
if adjust > 0:
time.sleep(adjust)
elif adjust < -10:
print("Can't keep up!", -adjust, "seconds behind.")