【问题标题】:How to perform an operation that takes a variable amount of time while maintaining a given average throughput如何在保持给定平均吞吐量的同时执行需要可变时间量的操作
【发布时间】:2017-09-21 19:40:47
【问题描述】:

我有一个函数,我想每秒调用 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)

这更好,但仍然不够好——不考虑执行循环的时间,如果在一次迭代中,_操作恰好比 1/TIMES_PER_SECOND 长得多,我们的吞吐量将太低。该操作平均耗时不到 1/TIMES_PER_SECOND,但代码需要处理确实耗时较长的情况。

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

【问题讨论】:

    标签: scheduling job-scheduling


    【解决方案1】:

    跟踪您希望查看操作是否以正确速率执行的时间。这将让您将实际时间与所需时间进行比较,如果它是肯定的,您可以睡觉。如果为负数,操作将连续运行,不休眠,直到我们赶上。

    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.")
    

    【讨论】:

      猜你喜欢
      • 2020-04-15
      • 1970-01-01
      • 1970-01-01
      • 2014-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多