Asyncio loop.call_later timing accuracy

Viewed 256
  • I am trying to have a function run periodically on the event loop
  • It is vital for the function to be called at the rate specified
  • I'm recursively scheduling the function to run using asyncio.call_later
  • It appears that asyncio.call_later does not call the function with the correct delay
  • The timer handle returned by call_later confirms that the delay is greater than expected

Why is the function not being called at the specified rate?

import asyncio
import time

def print_fps():
    global last_time

    time_now = time.time()
    dt = time_now - last_time
    if dt > 0:
        print(f"fps: {round(1/dt, 3)} [{round(dt,3)}s], target: {fps} [{round(1/fps,3)}s]")
    else:
        print("dt = 0")
    last_time = time_now

def loop_func():
    # print fps info
    print_fps()

    # schedule next iteration of loop
    loop.call_later(1/fps, loop_func)

async def main():
    loop_func()

last_time = time.time()
fps = 60

loop = asyncio.get_event_loop()
loop.create_task(main())
loop.run_forever()

Output:

fps: 31.446 [0.032s], target: 60 [0.017s]
fps: 32.693 [0.031s], target: 60 [0.017s]
fps: 32.172 [0.031s], target: 60 [0.017s]
fps: 31.663 [0.032s], target: 60 [0.017s]
fps: 32.001 [0.031s], target: 60 [0.017s]
fps: 30.549 [0.033s], target: 60 [0.017s]
fps: 34.486 [0.029s], target: 60 [0.017s]
fps: 31.366 [0.032s], target: 60 [0.017s]
fps: 31.743 [0.032s], target: 60 [0.017s]
fps: 30.057 [0.033s], target: 60 [0.017s]

cProfile reveals nothing is blocking the event loop

0 Answers
Related