转载:http://blog.csdn.net/avan_lau/article/details/6958497
最近在分析软件中画线效率问题,发现在画一些标志性符号的方法,存在瓶颈,占用较大的时间。而画这些符号的,则最终是调用TBitMap32.TextOut。大致状况如下:
TextOutSignWithAngle为画特殊符号方法,中间调用了API:GetObject用于获取LogFont信息,然后填充logFont角度信息,再调用API:CreateFontIndirect,设置创建后的字体Handle为bitmap32的字体handle,调用BitMap.TextOut,最后删除创建的字体对象。
原本分析代码认为:频繁创建字体并删除,这应该浪费不少时间(参考MSDN有关CreateFontIndirect说明)。后来建立一个字体列表,将创建后的字体,全部记录进去,每次进来先从字体列表中查找,有查到,则直接引用,否则才创建——因为CreateFontIndirect创建字体,可以持续使用。
按上述修改后,再次测试验证,发现性能没有提高多少。进而怀疑Textout应该是瓶颈。依据数据分析,也确实是,如下:
设TextOutSignWithAngle执行15000次,耗时1.40S(包含子方法);调用子方法BitMap32.TextOut,耗时1.20S。
最后分析,TBitmap32.TextOut源码
[delphi] view plaincopyprint?
- var
- Extent: TSize;
- begin
- UpdateFont;
- if not FMeasuringMode then
- begin
- if FClipping then
- ExTextOut();//节省码字时间,括号内参数省略
- else
- ExTextOut();
- end;
- Extent:= TextExtent(Text);
- Changed(MakeRect(....));
- end;
var Extent: TSize; begin UpdateFont; if not FMeasuringMode then begin if FClipping then ExTextOut();//节省码字时间,括号内参数省略 else ExTextOut(); end; Extent:= TextExtent(Text); Changed(MakeRect(....)); end;
依次逐行分析代码性能,除了最终的API:ExTextOut外,最耗时的,则属TExtExtent,计算这个,仅仅为了后续的Changed事件,这在实际画text时,并不需要。
TextExtent耗时为0.42S,而updatefont耗时0.01S,Changed约耗时可忽略不计(应该是没有事件处理)。
由此,我们可以单独使用ExTextout作为文字的输出,再加上最开始的那段字体列表优化,可减少0.5-0.7S。文字输出的耗时,执行15000次的耗时,可控制在0.8S以内。
BTW. 以上性能分析数据,借助于AQTime。
版权声明:本文为博主原创文章,未经博主允许不得转载。