用纯汇编来写strlen一定比C语言写的快吗?

2022-10-31 15:07:27 浏览数 (1)

先说答案,不一定。

事情是这样的,我在写操作系统,看到田宇大佬写的代码里面,strlen也是用汇编来写的,我很不解,这个不是可以用C来实现吗?难不成纯汇编更快?于是我就写了一个小程序来做实验。看看这两者的速度。

这个程序首先是随机生成了1E6长度的字符串,然后分别进行1000次计算大小,可以发现,C语言的函数运行的更快一些些。

代码语言:javascript复制
//测试strlen的速度

#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

int n = 1e6; //生成长度为1e6的字符串

char s[1000007];

void generate_string()
{
    //先删除s

    srand((unsigned)time(NULL));
    for (size_t i = 0; i < n; i  )
    {
        /* code */
        s[i] = 'a'   rand() % 26;
    }
    s[n] = '';
}

int _strlen_asm(char *s)
{
    register int __res;
    __asm__ __volatile__("cld	nt"
                         "repne	nt"
                         "scasb	nt"
                         "notl	%0	nt"
                         "decl	%0	nt"
                         : "=c"(__res)
                         : "D"(s), "a"(0), "0"(0xffffffff)
                         :);
    return __res;
}

int _strlen_c(char *s)
{
    register int __res = 0;
    while (s[__res] != '')
    {
          __res;
    }
    return __res;
}

int main()
{
    generate_string();
    time_t start, end;

    clock_t total_asm = 0;
    int times = 1000;
    for (int i = 0; i < times;   i)
    {
        start = clock();
        _strlen_asm(s);
        total_asm  = clock()-start;
    }

    printf("%lfn", 1.0*total_asm/times);

    clock_t total_c = 0;
    for (int i = 0; i < times;   i)
    {
        start = clock();
        _strlen_c(s);
        total_c  = clock()-start;
    }
    printf("%lfn", 1.0*total_c/times);
}

运行速度:

田宇大佬的汇编版本:平均517.047000ms

C语言版本:平均430.027000ms

可以看到C版本的运行的更快,快了16.8%。

考虑到可能是这两个函数执行先后性的影响,交换一下他们的先后顺序,得到的结果依然不变。

怀着疑问,再来看看他们编译后的汇编代码:也许jmp指令对于处理器的分支预测更友好?

代码语言:javascript复制
00000000004011de <_strlen_asm>:
  4011de:       55                      push   %rbp
  4011df:       48 89 e5                mov    %rsp,%rbp
  4011e2:       53                      push   %rbx
  4011e3:       48 89 7d f0             mov    %rdi,-0x10(%rbp)
  4011e7:       48 8b 75 f0             mov    -0x10(%rbp),%rsi
  4011eb:       b8 00 00 00 00          mov    $0x0,�x
  4011f0:       ba ff ff ff ff          mov    $0xffffffff,�x
  4011f5:       89 d1                   mov    �x,�x
  4011f7:       48 89 f7                mov    %rsi,%rdi
  4011fa:       fc                      cld    
  4011fb:       f2 ae                   repnz scas %es:(%rdi),%al
  4011fd:       f7 d1                   not    �x
  4011ff:       ff c9                   dec    �x
  401201:       89 ca                   mov    �x,�x
  401203:       89 d3                   mov    �x,�x
  401205:       89 d8                   mov    �x,�x
  401207:       5b                      pop    %rbx
  401208:       5d                      pop    %rbp
  401209:       c3                      ret    

000000000040120a <_strlen_c>:
  40120a:       55                      push   %rbp
  40120b:       48 89 e5                mov    %rsp,%rbp
  40120e:       53                      push   %rbx
  40120f:       48 89 7d f0             mov    %rdi,-0x10(%rbp)
  401213:       bb 00 00 00 00          mov    $0x0,�x
  401218:       eb 03                   jmp    40121d <_strlen_c 0x13>
  40121a:       83 c3 01                add    $0x1,�x
  40121d:       48 63 d3                movslq �x,%rdx
  401220:       48 8b 45 f0             mov    -0x10(%rbp),%rax
  401224:       48 01 d0                add    %rdx,%rax
  401227:       0f b6 00                movzbl (%rax),�x
  40122a:       84 c0                   test   %al,%al
  40122c:       75 ec                   jne    40121a <_strlen_c 0x10>
  40122e:       89 d8                   mov    �x,�x
  401230:       5b                      pop    %rbx
  401231:       5d                      pop    %rbp
  401232:       c3                      ret 

转载请注明来源:https://longjin666.cn/?p=1329

0 人点赞