在使用 CEF 的过程中, 我发现了一个现象: WPF 版的 CEF 比 Chrome 性能要差: 一些有动画的地方会掉帧 (例如, CSS 动画, 全屏图片拖动等), 视频播放的效果也没有 Chrome 流畅.
查了一下相关资料, 发现 CEFSharp.WPF 不是直接渲染在控件上的, 它的大概流程如下:
CEFSharp.WPF 的 ChromiumwebBrowser 控件本质上是一个图片
而是通过离屏渲染的方式渲染在缓冲区里,
绘制完成后, 然后将缓冲区的数据传递到 InteropBitmap 中去
将 InteropBitmap 作为 ChromiumWebBrowser 的图源更新
这个基本上是类似于 WPF 的视频播放器的做法: 先离屏渲染出图片, 在将图片更新到界面. 这个做法由于是使用的 WPF 的原生渲染方案, 可以说是 WPF 的原生控件的, 本身是有不少好处的:
可以支持透明背景
可以在上面叠加其它 WPF 控件
可以支持 WPF 的变形, 动画, 裁剪等特效
简单一句话, 是可以和 WPF 程序无缝集成的, 如果将 Web 界面作为控件嵌入式再方便不过的.
但是, 它这个实现是有代价的:
离屏渲染本身需要多一层工序,
有切换上下文和内存拷贝的开销.
更要命的是, 貌似目前 GPU 离线渲染视频效果还不是很好, 因此默认还把 gpu 加速给关了, 性能更下降了一截.
另外, InteropBitmap 传递图片内存的效率本身就不高, 不光吃 CPU, 还吃内存, 网上也有人讨论过.
- GPU and WPF https://github.com/cefsharp/CefSharp/issues/654
- Wpf's InteropBitmap together with GDI+: high CPU usage
针对这些问题, 有人建议使用 WritableBitmap 替换 InteropBitmap, 但貌似作者认为 InteropBitmap 的效率更好些. 我使用过 WritableBitmap 离屏渲染地图, 应该是能做到比当前更好的性能的.
也有人建议使用效率更高的 D3DImage(WPF 原生支持这个, 不过麻烦些), 可能作者觉得目前它的这个性能问题不是首要解决的目标吧, 也一直没有采纳.
最后说一下解决方法吧, 虽然在大部分的情况下, 当前的解决方案是能满足我们的需求的, 不过如果遇到非要解决的情况下, 可以使用下 WinFrom 版的 CEFSharp, 通过 WinFormHost 来集成到 WPF 程序中去.
WinFrom 版的 CEFSharp 应该是直接渲染的, 我试了一下, 效率基本上接近 Chrome, 并且由于他们的基础库是公用的, 在 WPF 程序中 WinFrom 版和 WPF 版的 CEF 是可以并存的, 用起来还算方便.
来源: http://www.bubuko.com/infodetail-2915099.html