c++ - 为什么 strcmp 比我的函数快这么多?

标签 c++ performance time strcmp

我写了一个函数,Str::Compare,它基本上是用另一种方式重写的strcmp。 在比较这两个函数时,在重复 500'000'000 次的循环中,strcmp 执行速度太快,大约快 x750 倍。

这段代码是在 C 库中编译的,-Os 参数处于事件状态:

int Str::Compare(char* String_1, char* String_2)
{
    char TempChar_1, TempChar_2;

   do
   {
        TempChar_1 = *String_1++;
        TempChar_2 = *String_2++;
   } while(TempChar_1 && TempChar_1 == TempChar_2);

   return TempChar_1 - TempChar_2;
}

那个函数的执行时间是3.058s,而strcmp只有0.004s

为什么会这样?

这也是我实现基准循环的方式:

int main()
{
     char Xx[] = {"huehuehuehuehuehuehuehuehuehuehuehuehuehue"},
          Yy[] = {"huehuehuehuehuehuehuehuehuehuehuehuehuehue"};
     for(int i = 0; i < 500000000; ++i)
         Str::Compare(Xx, Yy);
}

编辑: 在测试我编写的一些代码和优化后,大大提高了 Str::Compare 的速度。 如果之前 strcmpx750 倍,那么现在只有 x250。这是新代码:

int Str::Compare(char* String_1, char* String_2)
{
     char TempChar_1, TempChar_2, TempChar_3;

     while(TempChar_1 && !TempChar_3)
     {
          TempChar_1 = *String_1++;
          TempChar_2 = *String_2++;
          TempChar_3 = TempChar_1 ^ TempChar_2;
     }

     return TempChar_1 - TempChar_2;
}

新的执行时间是0.994s

最佳答案

我对此感到好奇并构建了一个测试程序:

#include <string.h>

compare(char* String_1, char* String_2)
{
    char TempChar_1,
         TempChar_2;

   do
   {
        TempChar_1 = *String_1++;
        TempChar_2 = *String_2++;
   } while(TempChar_1 && TempChar_1 == TempChar_2);

   return TempChar_1 - TempChar_2;
}


int main(){
    int i=strcmp("foo","bar");
    int j=compare("foo","bar");

    return i;
}

我用 gcc -S -Os test.c使用 gcc 4.7.3 将它编译成汇编器,得到以下汇编器:

    .file   "test.c"
    .text
    .globl  compare
    .type   compare, @function
compare:
.LFB24:
    .cfi_startproc
    xorl    %edx, %edx
.L2:
    movsbl  (%rdi,%rdx), %eax
    movsbl  (%rsi,%rdx), %ecx
    incq    %rdx
    cmpb    %cl, %al
    jne .L4
    testb   %al, %al
    jne .L2
.L4:
    subl    %ecx, %eax
    ret
    .cfi_endproc
.LFE24:
    .size   compare, .-compare
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "bar"
.LC1:
    .string "foo"
    .section    .text.startup,"ax",@progbits
    .globl  main
    .type   main, @function
main:
.LFB25:
    .cfi_startproc
    movl    $.LC0, %esi
    movl    $.LC1, %edi
    call    compare
    movl    $1, %eax
    ret
    .cfi_endproc
.LFE25:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3"
    .section    .note.GNU-stack,"",@progbits

我在 x86 汇编器中不是那么好,但据我所知,对 strcmp 的调用已被删除并简单地替换为常量表达式( movl $1, %eax )。因此,如果您在测试中使用常量表达式,gcc 可能会将 strcmp 优化为常量。

关于c++ - 为什么 strcmp 比我的函数快这么多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20734934/

相关文章:

c++ - 元组:没有调用 'get' 的匹配函数

c++ - 可以得到不包含头文件目录的警告或错误

javascript - Node.js - 检查字符串是否表示大量元素的有效日期时间的最快方法是什么?

performance - Lucene 内存空间索引性能不佳

java - 如何在旧版 Android 中降级 java.time 代码?

time - Modelica 仿真和方程初始化的总时间计算

c++ - VS 2015 "Build Dependencies -> Build Customization"总是触发 PreBuild 和 PostBuild

c++ - Eclipse C++ 构建问题

Android 远程方法 (AIDL) 与 Intents - 性能和电池使用情况

C++:将当前时间与下一个工作时间进行比较