使用汇编优化BCB6的itoa

今天写了个测试itoa性能的程序,做了1千万次itoa操作,主要代码如下:
char buf[64];
unsigned long t = GetTickCount();
for (int i = 0; i <= 10000000; ++i) {
    itoa(i, buf, 10);
}
unsigned long t2 = GetTickCount();
printf("last=%s, %u/n", buf, t2 - t);
 
分别使用VC++2003和C++BUILDER6编译,打开所有速度优化选项,结果发现性能相差很大。
VC最快用了2547ms,BCB最快用了4016ms。想想C运行库应该都是高度优化过的,怎么会有这么大的性能差距呢?
 
为了一探究竟,我翻出了itoa的源码,稍做修改(去掉了正负号处理)代码如下:
void myxtoa (unsigned long val,  char *buf,  unsigned radix)
{
        char *p;                /* pointer to traverse string */
        char *firstdig;         /* pointer to first digit */
        char temp;              /* temp char */
        unsigned digval;        /* value of digit */
        p = buf;
        firstdig = p;           /* save pointer to first digit */
        do {
            digval = (unsigned) (val % radix);
            val /= radix;       /* get next digit */
            /* convert to ascii and store */
            if (digval > 9)
                *p++ = (char) (digval - 10 + 'a');  /* a letter */
            else
                *p++ = (char) (digval + '0');       /* a digit */
        } while (val > 0);
        /* We now have the digit of the number in the buffer, but in reverse
           order.  Thus we reverse them now. */
        *p-- = '/0';            /* terminate string; p points to last digit */
        do {
            temp = *p;
            *p = *firstdig;
            *firstdig = temp;   /* swap *p and *firstdig */
            --p;
            ++firstdig;         /* advance to next two digits */
        } while (firstdig < p); /* repeat until halfway */
}
我使用myxtoa这个函数代替C运行库中的itoa,再编译测试,VC和BCB的编译结果都比原来快了几十毫秒(去掉了符号处理当然快了)。看来BCB对这段代码优化得不如VC好。查看BCB生成的汇编代码后发现,BCB对val /= radix的编译结果是通过存储器读操作数的,没有放到寄存器中。为了测试是该语句影响了性能,将val /= radix语句注释掉,在VC和BCB下重新编译,发现BCB的运行结果居然比VC快了2倍多,看来两个编译器对寄存器变量使用的不同造成了性能上的差异。
 
 为了证实自己的想法,我用汇编重写了myxtoa,用BCB编译,果然现在BCB版本跑的VC一样快了,基本两者都在几毫秒差距间波动。进一步使用__fastcall优化调用后,发现BCB版比VC版快了50-60ms,当然VC也能如此优化。下面是我改写的汇编代码BCB版(VC使用此代码只需对寄存器变量稍做修改即可):
void __fastcall myxtoa (unsigned long val, char *buf, unsigned radix)
{
        __asm {
            mov ebx, edx
            mov esi, ebx
        }
        do {
            __asm {
                xor edx, edx
                div ecx
            }
            if (_EDX > 9) {
                _EDX += ('a' - 10);
            }
            else {
                _EDX += '0';
            }
            __asm mov [ebx], dl
            ++_EBX;
        } while (_EAX > 0);
 
        /* We now have the digit of the number in the buffer, but in reverse
           order.  Thus we reverse them now. */
 
        __asm mov byte ptr [ebx], 0
        --_EBX;
        do {
            __asm {
                mov cl, [ebx]
                mov al, [esi]
                mov [ebx], al
                mov [esi], cl
            }
            --_EBX;
            ++_ESI;
        } while (_ESI < _EBX); /* repeat until halfway */
}
总结,对寄存器变量的优化安排将有效提升程序性能,不过一般这种事情交给C++编译器就可以了,现在PC上的编译器已经足够强了。
 

你可能感兴趣的:(性能,VC,BCB)