MacOS/X 下的 Qt 4.6.x:小部件更新性能之谜
我正在开发一个基于 Qt 的 MacOS/X 音频计量应用程序,其中包含音频计量小部件(可能有很多),每个小部件应该每 50 毫秒(即 20Hz)更新一次。
该程序可以工作,但是当同时更新大量仪表时,它会占用大量 CPU 时间并且可能陷入困境(旋转色轮,哦不!)。
奇怪的是:最初这个应用程序只会在仪表值发生变化时调用仪表小部件上的 update() ,因此整个仪表小部件将每 50 毫秒重绘一次。然而,我认为我会很聪明,只计算实际需要重绘的仪表面积,并且只重绘小部件的该部分(例如 update(x,y,w,h),其中 y 和 h 是根据仪表的旧值和新值计算)。然而,当我实现这一点时,它实际上使 CPU 使用率提高了四倍(!)...尽管应用程序每秒绘制的像素减少了 50%。
谁能解释为什么这种优化实际上是一种悲观化?我在这里发布了一个演示效果的简单示例应用程序:
http://www.lcscanada .com/jaf/meter_test.zip
当我编译 (qmake;make) 上面的应用程序并像这样运行它时:
$ ./meter.app/Contents/MacOS/meter 72
Meter: Using numMeters=72 (partial updates ENABLED)
... 顶部显示使用 ~50% CPU 的进程。
当我禁用 smart-partial-updates 逻辑时,通过像这样运行它:
$ ./meter.app/Contents/MacOS/meter 72 disable_partial_updates
Meter: Using numMeters=72 (partial updates DISABLED)
... top 显示仅使用 ~12% CPU 的进程。啊?这种情况不应该占用更多的CPU,而不是更少吗?
我尝试使用 Shark 分析该应用程序,但结果对我来说意义不大。 FWIW,我在 8 核 Xeon Mac Pro 上运行 Snow Leopard。
I'm working on a Qt-based MacOS/X audio metering application, which contains audio-metering widgets (potentially a lot of them), each of which is supposed to be updated every 50ms (i.e. at 20Hz).
The program works, but when lots of meters are being updated at once, it uses up lots of CPU time and can bog down (spinny-color-wheel, oh no!).
The strange thing is this: Originally this app would just call update() on the meter widget whenever the meter value changed, and therefore the entire meter-widget would be redrawn every 50ms. However, I thought I'd be clever and compute just the area of the meter that actually needs to be redrawn, and only redraw that portion of the widget (e.g. update(x,y,w,h), where y and h are computed based on the old and new values of the meter). However, when I implemented that, it actually made CPU usage four times higher(!)... even though the app was drawing 50% fewer pixels per second.
Can anyone explain why this optimization actually turns out to be a pessimization? I've posted a trivial example application that demonstrates the effect, here:
http://www.lcscanada.com/jaf/meter_test.zip
When I compile (qmake;make) the above app and run it like this:
$ ./meter.app/Contents/MacOS/meter 72
Meter: Using numMeters=72 (partial updates ENABLED)
... top shows the process using ~50% CPU.
When I disable the clever-partial-updates logic, by running it like this:
$ ./meter.app/Contents/MacOS/meter 72 disable_partial_updates
Meter: Using numMeters=72 (partial updates DISABLED)
... top shows the process using only ~12% CPU. Huh? Shouldn't this case take more CPU, not less?
I tried profiling the app using Shark, but the results didn't mean much to me. FWIW, I'm running Snow Leopard on an 8-core Xeon Mac Pro.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
GPU 绘图比让 CPU 计算要重绘的部分要快得多(至少对于 OpenGL 来说,这是考虑在内的,我得到了《OpenGL superible》一书,它指出 OpenGL 是为了重绘而构建的,而不是为了重绘)绘制增量,因为这可能需要做很多工作)。即使您使用软件渲染,这些库也经过高度优化,可以正确且快速地完成其工作。所以仅仅重画就是最先进的。
GPU drawing is a lot faster then letting CPU caclulate the part to redraw (at least for OpenGL this takes in account, I got the Book OpenGL superbible, and it states that OpenGL is build to redraw not, to draw delta as this is potentially a lot more work to do). Even if you use Software Rendering, the libraries are higly optimzed to do their job properly and fast. So Just redrawing is state of art.
我的 Linux 机器上的 FWIW
top
显示大约 10-11% 没有部分更新,12% 使用部分更新。不过,我必须请求 400 米才能获得 CPU 使用率。也许只是 Qt 设置绘制区域的开销实际上使您的绘制时间相形见绌?毕竟你的绘画非常简单,只是两个矩形填充。
FWIW
top
on my Linux box shows ~10-11% without partial updates and 12% using partial updates. I had to request 400 meters to get that CPU usage though.Perhaps it's just that the overhead of Qt setting up a paint region actually dwarfs your paint time? After all your painting is really simple, it's just two rectangular fills.