在什么情况下冻结 WPF 对象对性能有很大好处?
WPF 中的许多类型派生自 Freezable
。 它为可变 POCO 对象提供了不变性,并且显然可以在某些情况下提高性能。
有没有人发现冻结 WPF 应用程序中的对象可以极大地提高性能? 如果是这样,那么哪些物品在冷冻时表现出最大的性能差异?
(请注意,我也发布了一个类似但不同的问题)
Many types in WPF derive from Freezable
. It provides immutability to mutable POCO objects and, apparently, allows for improved performance in certain situations.
Has anyone found that freezing objects within their WPF application has greatly improved performance? If so, then which items gave the biggest performance difference when being frozen?
(Note that I have posted a similar but different question too)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可能对我使用 Freezable 的经历感兴趣:
我曾经使用 muPdf 编写了一个 PDF 查看器,它渲染位图,我使用 WPF 渲染。 对性能有很大帮助的是,我可以在后台线程上渲染页面位图,冻结它们,然后将它们传递给 UI 线程。 很高兴 WPF 不会复制图像来冻结它,但在后台线程上完成所有这些准备工作的能力对我来说是主要的好处。
据我了解,所有视觉效果都需要冻结,以便 WPF 渲染线程可以安全地渲染它们。 如果渲染大型未冻结的视觉效果,当 WPF 渲染它们时,它们将被克隆为冻结的视觉效果。 如果您事先冻结静态位图,WPF 可以仅与渲染线程共享指针而无需克隆。 如果 WPF 不知道对象自上次渲染以来是否发生了更改,则未冻结的对象甚至可能会被重复复制。 冻结对象消除了所有这些复制的需要。
You might be interested in my experiences with Freezable:
I once wrote a PDF viewer using muPdf which renders bitmaps, that I render with WPF. What helps performance greatly is that I can render the page bitmaps on a background thread, freeze them, and then pass them to the UI thread. It is nice that WPF does not copy the image to freeze it, but the ability to do all this preparation on a background thread was the key benefit for me.
From what I understand, all visuals need to be frozen so they can be safely rendered by the WPF render thread. If you render large unfrozen visuals, they will get cloned to frozen ones when WPF renders them. If you freeze your static bitmaps beforehand, WPF can just share the pointer with the render thread without cloning. Unfrozen objects may even get copied repeatedly if WPF is not aware wether the object is changed from the last time it was rendered. Frozen objects eliminate the need for all this copying.
如果您使用 Image 控件(而不是使用 Freeze 方法),则可能会发生这些潜在的内存泄漏:
a) 您使用 BitmapImage 作为 Image 源并且不释放 BitmapImage:
b) 您分配多个 BitmapImage 作为 Image 源并且不释放您使用的所有 BitmapImage(类似于 (a))。 这一功能在 .Net 3.5 中引入:
来源:WPF 性能
These potential memory leaks could happen if you use the Image control (and not use Freeze method):
a) You use BitmapImage as the Image source and do not release the BitmapImage:
b) You assign multiple BitmapImage as the Image source and do not release all of the BitmapImage you used (similar to (a)). This one introduced in .Net 3.5:
Source: WPF Performance
尽管您已经接受了答案,但只是想记录一个不同版本的答案,以更好地帮助我。
来自 MSDN(少量编辑):
并且,解释用法的代码:
Though you have already accepted the answer, just wanted to log a different version of the answer that helped me better.
From MSDN (minor edit):
And, the code to explain the usage:
我开发了一个高性能图像查看器应用程序。 我们在后端有代码,每帧创建一个新的位图,并将该位图写入屏幕,如下所示:
在测试过程中,我们注意到在中等大小的图像 (1080p) 下达到 30+ FPS 时会出现严重的闪烁。 修复? 只需先冻结位图,然后再将其设置为 image.Source。 不再有破坏产品的性能错误。 现在我试着冷冻一切我能冷冻的东西。
I developed a high-performance image viewer application. We had code on the back-end that created a new bitmap every frame and wrote that bitmap to the screen like so:
During testing, we noticed that there was a terrible flickering while going 30+ FPS with moderately-sized images (1080p). The fix? Just freeze the bitmap before setting it to the image.Source. No more product-killing performance bug. Nowadays I try to freeze everything I can.