Win7 x64上DrawText性能不佳

我注意到,在MFC应用程序中,我正在开发一个拖动滚动条以平滑向下滚动文档的框架,当一个包含一段文本的块显示在屏幕上时,帧率会下降到不连续的水平,但是当它不在屏幕上时,会变得光滑平滑。 调查性能,我发现单一的CDC::DrawText调用的文本段负责。 这是在一个优化的发布版本。

我使用QueryPerformanceCounter来获得DrawText调用的高分辨率度量,如下所示:

 QueryPerformanceCounter(...); pDC->DrawText(some_cstring, some_crect, DT_WORDBREAK); QueryPerformanceCounter(...); 

该文本是unicode,lorem-ipsum样式填充符,长度为865个字符,并在给定矩形和字体(Segoe UI, lfHeight = -12,标准正文文本大小)的情况下封装了7位和1位的行。 从我的测量结果来看,这个电话平均需要7.5毫秒,21毫秒的单峰。 (注意跟上一个60Hz的显示器,你会得到大约16ms来渲染每个更新。)

我尝试了一些改进来提高性能:

  • 删除DT_WORDBREAK提高了大约1ms的性能(快了大约7倍),但是由于只有一行文本正在屏幕上显示,并且有超过7行的文字中断,这似乎暗示了瓶颈在其他地方。
  • 我以透明模式绘制文本( SetBkMode(TRANSPARENT) )。 所以我尝试了一个不透明的模式,用一个坚实的背景填充。 没提升。
  • 我以为ClearType渲染可能是责怪。 我将字体lfQualityNONANTIALIASED_QUALITY更改为NONANTIALIASED_QUALITY 。 它看起来像边缘和边缘的废物,没有任何改善。
  • 根据评论build议,我正在使用一个CMemDC,但我摆脱了它,并直接绘制。 它像疯了一样闪烁,没有改善。

这是运行在Windows 7 64位笔记本电脑与英特尔酷睿2双核P8400 @ 2.26 GHz和4 GB内存 – 我不认为这是一个缓慢的系统。

每次绘制时我都会调用DrawText(),这显然会影响性能,这是一个很慢的function,尤其是如果几个文本块可以同时显示的话。 这足以让体验感觉呆滞。 不过,Firefox可以使用更多的文本在ClearType中渲染一个像这样的页面,而且看起来很好。 我究竟做错了什么? 我该如何解决实际的DrawText调用的糟糕performance?

在每次刷新时绘制文本都是浪费的。 使用双缓冲 ,也就是说,绘制一个离屏位图,只是将其投影到屏幕上。 然后,对于滚动,只需要复制大部分位图或根据需要横向,然后只绘制无效区域(在将结果传送到屏幕之前)。

如果结果太慢,请将绘制的文本保存在离屏位图中,然后用blit而不是绘制。

干杯&hth。,

根据这个德国的博文 ,这个问题与支持亚洲语言字体有关。 如果你在XP中启用这些,你会得到同样的perf命中。 在Vista / 7中,它们是默认启用的,不能关闭它们。

编辑:也许,使用不同的字体可能会有所帮助..(一个不包含亚洲字符)。

用户无法在7毫秒内读取7行的文本,因此通话本身速度不够快。

显示器的60 Hz刷新率完全不相关。 您不需要为每个帧重新渲染相同的文本。 视频卡将高兴地再次发送相同的像素到屏幕上。

所以,我想你有另一个问题。 你是否想知道滚动文字? 请问你真的有问题,而不是假设DrawText是罪魁祸首。

为了打破单词分隔的文字,DrawText需要反复尝试获得一个文本块的宽度,看看它是否合适,然后把余下的部分放在一边。 每次通话都需要这样做。 如果你的文本不变,这是一个不必要的开销。 作为解决方法,您可以自行测量文本并插入临时换行符,并删除DT_WORDBREAK标志。

你考虑过Direct2D / DirectWrite吗?

无论如何,它应该更好地工作,如果你只是一次绘制文本到自己的内存直流和blit,直到你想要在每一次迭代绘制任何直流。