Trying to simulate constant byte rate. Confusion with time.sleep results

做~自己de王妃 提交于 2019-11-29 16:34:35

Conclusion

Thanks to @J.F.Sebastian and his code, I came to learned that:

  • Its better to use use a deadline as a time reference than create to a new reference each loop
  • Using a deadline "amortizes" the imprecision of time.sleep, oscilating a bit around the desired bitrate but resulting in an correct(and much more constant) average.
  • You only need to you use time.time() once, that means less calculations imprecisions.

As a result, I get a constant 32000 B/s some times oscilating to 31999 and very rarely to 31745
Now I can hear the music without any lag or jitter!

I tried using @J.F.Sebastian implentation using only the % operator to sleep the remainder, but the KB/s oscilate strangelly, so I decided to keep the deadline implementation, which suffers imprecision by keeping adding a float value. Nevertheless, the overall result is enough for my needs.
Thank you everyone.

Final Code

def read(self):
    self.deadline += 0.020  
    delay = self.deadline - time.perf_counter()
    if delay > 0:
        time.sleep(delay)
    return self._read()

As you can read in the question you linked, there are no guarantees for sleep and it can vary widely depending on the OS. But 4 ms resolution seems sufficient if you want to send data every 20 ms. There should be no need to improve your sleep() accuracy.

On Debian, at around 0.02 seconds input, your computer sleeps around 12 / 10 of the time you ask it to. 10 / 12 * 32 is 26.6, so it makes sense if you only receive 27 KB/s.

Instead of sleeping 0.02 seconds, use an adaptive sleeping time. Measure how long the last iteration took (sleeping + sending the data), and shorten your sleeping time to make the whole iteration take 0.02 seconds.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!