在论坛或者邮件组里经常会有朋友提到,要想提高图形应用程序的性能必须要使用本地代码(C/C++)来开发。我们也经常听说本地代码在三维图形的操作上要比托管代码快得多。然而,事实并非完全如此,本文会通过多个平台上的实验数据来探讨托管代码和本地代码在图形操作上的性能问题。KeywordsGDI, C++, C#, Windows Mobile, .NET Compact Framwork, performance本地代码测试我们先来看看本地代码测试程序。代码很简单,仅仅是为了测试。这段程序绘制了一个矩形位图域并创建了相应的DC(device context),然后重复10000次以下两个操作:一是不断的用灰色填充矩形域,二是不断在矩形域中间绘制绿色的椭圆。这里椭圆的长轴短轴都是在不断变化的,这可以避免显示驱动缓存对我们的测试造成的影响。主要代码如下:
...
screenDC = GetWindowDC(NULL);
bufferDC = CreateCompatibleDC(screenDC);
oldPen = (HPEN)SelectObject(bufferDC, CreatePen(PS_NULL, 0, NULL));
oldBrush = (HBRUSH)SelectObject(bufferDC, CreateSolidBrush(#00ff00));
hBufferBmp = CreateCompatibleBitmap(screenDC, BOX_WIDTH, BOX_HEIGHT);
oldObject = SelectObject(bufferDC, hBufferBmp);
rect.top = 0;
rect.left = 0;
rect.right = BOX_WIDTH;
rect.bottom = BOX_HEIGHT;
for(i = 0 ; i < GDI_ITERATIONS_PER_REPORT ; i++)
{
width += xop;
height+= yop;
if((width >= BOX_WIDTH) || (width <= 0))
xop *= -1;
if((height >= BOX_HEIGHT) || (height <= 0))
yop *= -1;
r += rop;
g += gop;
b += bop;
if((r > 254) || (r< 1))
rop *= -1;
if((g > 254) || (g< 1))
gop *= -1;
if((b> 254) || (b< 1))
bop *= -1;
boxBrush = CreateSolidBrush(RGB(r, g, b));
FillRect(bufferDC, &rect, boxBrush);
DeleteObject(boxBrush);
Ellipse(bufferDC, width, height, BOX_WIDTH - width, BOX_HEIGHT - height);
Ellipse(bufferDC, height, width, BOX_WIDTH - height, BOX_HEIGHT - width);
BitBlt(screenDC, left, top, left + BOX_WIDTH, top + BOX_HEIGHT,
bufferDC, 0, 0, SRCCOPY);
}
...
运行效果如图:
测试结果是,在Windows Mobile 5.0的模拟器上,执行循环的速度为490次每秒(当然这跟你PC机的性能是有关的)。每一次操作包括了填充矩形和绘制两个椭圆的过程。在一台Windows Mobile 5.0 Dell Axim x51(PXA270处理器)的实际设备上,这个程序可以达到250次每秒的循环速度。