2

我想在同一个应用程序中使用 Twisted 和 GTK+。我正在使用 gtk2reactor,使我的所有代码都正确地非阻塞,并且通常它工作得很好。

但是,当我运行 (HTTP) 下载时,GUI 变得无响应且滞后。就好像某些东西在扭曲的块中(在很短的时间内)并且反应器没有足够频繁地处理 GTK 事件。基本上,我正在使用:

factory = twc.HTTPDownloader(url, filename)
reactor.connectTCP(host, port, factory)

这是一个小 PyGtk 程序来演示这个问题。我那里只有一个虚拟进度条来显示一些动画,但在成熟的程序中问题也很明显。只要下载正在运行,滚动或在 GtkNotebook 选项卡之间切换时就会出现明显的延迟。

这是预期的,还是我做错了什么?我以前做过 GTK + Twisted 应用程序,但从未注意到这一点,但我也从未在 twisted 中传输过较大的文件(~300 MB)。也许在将控制权交还给主循环之前,twisted 选择了太大的块大小并保持忙碌太久(〜 100 毫秒?)?我应该为 GTK 和扭曲循环使用单独的线程吗?

4

1 回答 1

1

在我给你任何关于解决这个问题的建议之前,我应该注意,每当遇到这样的性能问题时,你应该分析你的应用程序,看看什么是花费最多时间的。您可以使用探查器,例如cProfile;或者可能是statprof,或者可能是Geoff Greer 的这个很酷的 hack,它专门用于找出阻塞 Twisted 反应堆的原因。客观的数据总是比猜想的好,你的具体数据只能从你的具体环境中获得。

也就是说,我确实对你有一些猜想。这里的问题很可能是文件 I/O。非阻塞文件 I/O 对 Twisted 来说是个痛处,因为如果不启动线程基本上是不可能的,所以不清楚如何构建最终适合未来特定平台的可移植 API API。尽管如此,Twisted应该有一些东西可以为你抽象出线程部分。

HTTPDownloader,具体来说,阻塞文件写入会导致反应器卡住并且您的 GUI 冻结。你可以覆盖pagePart做一些非阻塞的事情;但是,这意味着您需要对对象的属性进行流量控制——例如告诉它——或者如果你的磁盘速度较慢,你可能最终会在内存中缓冲所有约 300MB 的文件。HTTPPageDownloadertransportpauseProducing

如果您使用新的AgentAPI,您可能会发现所有这些都更容易。您仍然需要进行自己的非阻塞文件 I/O,但至少deliverBodyAPI 将为您提供一个可以transport方便地访问的对象,pauseProducing您可以使用可以直接调用的方法,而不是子类化几个不同的事物并涉足几个抽象层(ClientFactory、、、, ) 来访问它。HTTPClientFactoryHTTPDownloaderHTTPPageDownloader

我意识到在 Twisted 中应该更容易管理流控制,我很抱歉设置起来有点繁琐。我知道,我们正在努力。

于 2013-03-31T22:12:56.913 回答