- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
[更新]我正在使用 Twisted 22.4.0 和 Python 3.9.6
我正在尝试编写一个必须以 250Hz 频率运行事件循环的异步应用程序。到目前为止,Twisted 对于我的应用程序来说还不够快(但我想知道是否可以解决这个问题)。在 Windows 10 i5 笔记本电脑上,我在 LoopingCall 中可以达到的最高频率约为 50hz。当我调整以下代码在 50hz 下运行正常并成功打印出“用了 1.002 秒”,但在 100Hz 下,代码通常需要 1.5 秒才能运行,我需要我的代码能够以 .004(250Hz)运行。
from twisted.internet.task import LoopingCall
from twisted.internet import reactor
import time
class Loop():
def __init__(self, hz):
self.hz = hz
self.lc = LoopingCall(self.fast_task)
self.num_calls = 0
self.lc.start(1/hz)
reactor.run() # **Forgot to add this the first time**
def fast_task(self):
if self.num_calls == 0:
self.start_time = time.time()
if self.num_calls == self.hz:
print("Stopping reactor...")
print(f"took: {time.time() - self.start_time} sec")
reactor.stop()
return
self.num_calls += 1
if __name__ == "__main__":
l = Loop(100)
上面的代码通常需要大约 1.5 秒才能运行。我的问题:有什么方法可以在 Windows 上的 Twisted 中加速这个事件循环吗?
我在 asyncio 中运行了一些类似的代码,asyncio 绝对可以在我的笔记本电脑上处理 250Hz 的循环。所以我接下来尝试的事情之一是将 asyncioreactor 与 Twisted 结合使用。事实证明,它仍然需要与上面不使用 asyncioreactor 的代码相同的时间。
但是,对于我的用例,我喜欢 Twisted 的简单性 - 我需要一些 TCP 服务器和客户端以及一些 UDP 服务器和客户端以及一些其他繁重的 I/O 处理。
另一个注意事项,我确实找到了 Twisted 的这张票 ( https://twistedmatrix.com/trac/ticket/2424 ),我在其中发现 [编辑](Twisted 的作者 - Glyph - 选择不移动到基于单调的时间,除非有 API更改,据我所知还没有实现,除非与 asyncioreactor 一起使用?)。这也让我担心将 Twisted 用作可靠的高频事件循环,例如 NTP 时钟调整。现在,可能是在引擎盖下使用 asyncio(使用 asyncioreactor)解决了这个问题,但它似乎并没有提供任何速度优势。
[更新 2] 这可能解决了我的问题:我使用以下代码调整了 Windows sleep 分辨率,现在我的 LoopingCall 似乎能够以 250Hz 的频率在 1 秒内可靠地运行上述代码,并且可靠地高达 1000Hz:
from ctypes import windll
windll.winmm.timeBeginPeriod(1) # This sets the time sleep resolution to 1 ms
[更新 3]
我已经包含了我用来使用 aysncioreactor 创建循环的代码。
注意:您会注意到我正在使用 WindowsSelectorEventLoopPolicy() - 这是因为没有安装最新的 Visual C++ 库(不过不确定这是否是重要信息)
注意 2: 我是 twisted 的新手,所以我可能会错误地使用它(asyncioreactor 的使用,或实际的 LoopingCall - 尽管 LoopingCall 看起来非常简单)
注3:我在 Windows 10 v21H2 上运行,处理器:1.6GHz i5
v21H2 在这里很重要,因为它在 v2004 之后:
发件人:https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod
Prior to Windows 10, version 2004, this function affects a globalWindows setting. For all processes Windows uses the lowest value (thatis, highest resolution) requested by any process. Starting withWindows 10, version 2004, this function no longer affects global timerresolution. For processes which call this function, Windows uses thelowest value (that is, highest resolution) requested by any process.For processes which have not called this function, Windows does notguarantee a higher resolution than the default system resolution.
为了看看我是否能证明这一点,我试过在不调用 timeBeginPeriod(1) 的情况下运行 Windows Media Player、Skype 和其他程序(认为另一个进程的另一个程序会设置较低的分辨率,并且会影响我的程序。但这并没有改变您在下面看到的时间。
注意事项 4:3 秒运行的时间(每次运行 3 次)@ 1000Hz:
asyncioreactor with timeBeginPeriod(1): [3.019, 3.029, 3.009]
asyncioreactor with no timeBeginPeriod(1): [42.859, 43.65, 43.152]
no asyncioreactor with timeBeginPeriod(1): [3.012, 3.519, 3.146]
no asyncioreactor, no timeBeginPeriod(1): [45.247, 44.957, 45.325]
我使用 asyncioreactor 实现
import asyncio
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
from twisted.internet import asyncioreactor
asyncioreactor.install()
from twisted.internet.task import LoopingCall
from twisted.internet import reactor
import time
from ctypes import windll
windll.winmm.timeBeginPeriod(1)
class Loop():
def __init__(self, hz=1000):
self.hz = hz
...
...
最佳答案
解决我的问题:
我使用以下代码调整了 Windows sleep 分辨率,现在我的 LoopingCall 似乎能够在 250Hz 下在 1 秒内可靠地运行上述代码,并且可靠地高达 1000Hz:
from ctypes import windll
windll.winmm.timeBeginPeriod(1) # This sets the time sleep resolution to 1 ms
关于python - 我可以从 Twisted LoopingCall 返回的最高保真度约为 100 毫秒(0.1 秒),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72772146/
我是一名优秀的程序员,十分优秀!