我注意到在MFC应用程序中我正在开发的同时拖动滚动条以平滑地向下滚动文档,当屏幕上包含大约一段文本的块时,帧速率会下降到不连续的水平,但是当它是屏幕外。调查性能,我发现单个CDC::DrawText
调用负责的文本段落。这是一个优化的发布版本。
我使用QueryPerformanceCounter
来获取只是 DrawText调用的高分辨率度量,如下所示:
QueryPerformanceCounter(...);
pDC->DrawText(some_cstring, some_crect, DT_WORDBREAK);
QueryPerformanceCounter(...);
文本是unicode,lorem-ipsum样式填充符,长度为865个字符,并且在给定矩形和字体的情况下包裹7位和1位线(Segoe UI,lfHeight
= -12,标准正文尺寸)。从我的测量结果来看,单独调用 平均需要7.5毫秒,奇数峰值需要21毫秒。 (注意为了跟上60Hz的监视器,你需要大约16ms来渲染每次更新。)
我尝试进行一些更改以改善效果:
DT_WORDBREAK
会将性能提升到大约1毫秒(大约快7倍),但只有一行文字才会显示在屏幕上,并且只有超过7行有字断行,这似乎是向我建议瓶颈在别处。SetBkMode(TRANSPARENT)
)绘制文字。所以我尝试了带有实心背景填充的不透明模式。没有改善。lfQuality
从CLEARTYPE_QUALITY
更改为NONANTIALIASED_QUALITY
。它看起来像带有锋利边缘的垃圾,而且没有任何改进。这是在配备Intel Core 2 Duo P8400 @ 2.26 GHz和4 GB RAM的Windows 7 64位笔记本电脑上运行 - 我不认为它是一个慢速系统。
我每次绘制时都会调用DrawText(),这显然会使用如此慢的函数来破坏性能,特别是如果这些文本块中的几个一次可见的话。这足以让体验变得迟钝。但是,Firefox可以使用更多文本在ClearType中呈现这样的页面,并且似乎可以很好地应对。我究竟做错了什么?如何解决实际DrawText调用的糟糕表现?
答案 0 :(得分:7)
每次刷新时绘制文本都是浪费。使用双缓冲,即在屏幕外位图中绘制并将其blit到屏幕上。然后,对于滚动,只需根据需要向上或向下或横向复制大部分位图,然后仅绘制无效区域(在将结果blit到屏幕之前)。
如果即使结果太慢,也要将绘制的文本保留在屏幕外的位图中,然后使用blit而不是绘制。
干杯&第h。,
答案 1 :(得分:2)
根据this german blogpost,问题与支持亚洲语言字体有关。如果在XP中启用它们,则会获得相同的性能。在Vista / 7中,它们默认启用,您无法将其关闭。
编辑:也许,使用不同的字体可能会有所帮助..(不包含亚洲字符的那种)。
答案 2 :(得分:2)
用户无法在7毫秒内读取7行文本,因此调用本身足够快。
显示器的60 Hz刷新率完全无关紧要。您不需要为每个帧重新渲染相同的文本。显卡将很高兴地再次向屏幕发送相同的像素。
所以,我知道你有另一个问题。你是否想知道滚动文字?请问你真正遇到的问题,而不是假设DrawText是罪魁祸首。
答案 3 :(得分:1)
为了打破单词分隔符上的文本,DrawText需要反复尝试获取文本块的宽度以查看它是否合适,然后取余数并完成。它需要在每次通话时都这样做。如果您的文本不变,这是一个不必要的开销。作为解决方法,您可以自己测量文本并插入临时换行符并删除DT_WORDBREAK标志。
答案 4 :(得分:0)
你考虑过Direct2D / DirectWrite吗?
无论如何,如果您只是将文本绘制到自己的内存中,并且将每次迭代绘制到任何想要的DC上,那么它应该会更好。