为何Linux下libc的putchar比直接系统调用write更快?
直接调用syscall比putchar慢2.5倍的反常现象
我正在针对Linux平台做代码深度优化,搭建了一个基于rdtsc的时钟周期计时框架,原本想通过直接调用Linux系统调用来替代libc函数提升性能(注:每次最多输出一个无格式字符)。但测试结果却显示putchar的速度比直接调用syscall快两倍多(时钟周期通过rdtsc获取,以64位十六进制整数展示,差值较小时补充十进制数值)。
注意:测试无重复,仅执行一次以下代码进行计时。
syscall测试代码及结果
汇编代码:
# %rdi contains a string movq $1 , %rax # system call 1: write movq %rdi, %rsi # what: char pointer movq $1 , %rdi # where: stdout movq $1 , %rdx # how many bytes: 1 syscall
计时结果:
__________________________________ RDTSC 后值: 0x0002c22fbac1c7b5 RDTSC 前值: 0x0002c22fbabf4d1f 时钟周期: 0x0000000000027a96 时钟周期: 162454
putchar测试代码及结果
汇编代码:
# %rdi contains a string mov %rdi, %rsi xor %edi, %edi movb (%rsi), %dil call putchar
计时结果:
__________________________________ RDTSC 后值: 0x0002c221713726cd RDTSC 前值: 0x0002c2217136469f 时钟周期: 0x000000000000e02e 时钟周期: 57390
注意:尽管仅展示一组结果,但多次测试均显示syscall方法的速度约慢2.5倍。
疑惑:putchar的内部执行流程反而更复杂
根据GDB单步调试得到的putchar内部执行流程来看,这个结果尤为反常,流程如下:
IO_validate_vtable (vtable=0x7ffff7e16600 <_IO_file_jumps>) at ./libio/libioP.h:943 943 ./libio/libioP.h: No such file or directory. (gdb) __GI__IO_file_doallocate (fp=0x7ffff7e1a780 <_IO_2_1_stdout_>) at ./libio/libioP.h:947 947 in ./libio/libioP.h (gdb) __GI__IO_file_stat (fp=0x7ffff7e1a780 <_IO_2_1_stdout_>, st=0x7fffffffde90) at ./libio/fileops.c:1146 1146 ./libio/fileops.c: No such file or directory. (gdb) 1147 in ./libio/fileops.c (gdb) __GI___fstat64 (fd=1, buf=0x7fffffffde90) at ../sysdeps/unix/sysv/linux/fstat64.c:29 29 ../sysdeps/unix/sysv/linux/fstat64.c: No such file or directory. (gdb) 30 in ../sysdeps/unix/sysv/linux/fstat64.c (gdb) 35 in ../sysdeps/unix/sysv/linux/fstat64.c (gdb) __GI___fstatat64 (fd=1, file=0x7ffff7dd846f "", buf=0x7fffffffde90, flag=4096) at ../sysdeps/unix/sysv/linux/fstatat64.c:153 153 ../sysdeps/unix/sysv/linux/fstatat64.c: No such file or directory. (gdb) 163 in ../sysdeps/unix/sysv/linux/fstatat64.c (gdb) fstatat64_time64_stat (flag=4096, buf=0x7fffffffde90, file=0x7ffff7dd846f "", fd=1) at ../sysdeps/unix/sysv/linux/fstatat64.c:98 98 in ../sysdeps/unix/sysv/linux/fstatat64.c (gdb) __GI___fstatat64 (fd=1, file=0x7ffff7dd846f "", buf=0x7fffffffde90, flag=4096) at ../sysdeps/unix/sysv/linux/fstatat64.c:166 166 in ../sysdeps/unix/sysv/linux/fstatat64.c (gdb) __GI__IO_file_doallocate (fp=0x7ffff7e1a780 <_IO_2_1_stdout_>) at ./libio/filedoalloc.c:86 86 ./libio/filedoalloc.c: No such file or directory. (gdb) 91 in ./libio/filedoalloc.c (gdb) __gnu_dev_major (__dev=34817) at ../include/sys/sysmacros.h:47 47 ../include/sys/sysmacros.h: No such file or directory. (gdb) 91 ./libio/filedoalloc.c: No such file or directory. (gdb) 94 in ./libio/filedoalloc.c (gdb) 97 in ./libio/filedoalloc.c (gdb) 101 in ./libio/filedoalloc.c (gdb) __GI___libc_malloc (bytes=bytes@entry=1024) at ./malloc/malloc.c:3287 3287 ./malloc/malloc.c: No such file or directory. (gdb) 3294 in ./malloc/malloc.c (gdb) 3295 in ./malloc/malloc.c (gdb) ptmalloc_init () at ./malloc/arena.c:315 315 ./malloc/arena.c: No such file or directory. (gdb) ptmalloc_init () at ./malloc/arena.c:313 313 in ./malloc/arena.c (gdb) 321 in ./malloc/arena.c (gdb) 0x00007ffff7ca1a31 in tcache_key_initialize () at ./malloc/malloc.c:3162 3162 ./malloc/malloc.c: No such file or directory. (gdb) 318 ./malloc/arena.c: No such file or directory. (gdb) 321 in ./malloc/arena.c (gdb) tcache_key_initialize () at ./malloc/malloc.c:3162 3162 ./malloc/malloc.c: No such file or directory. (gdb) __GI___getrandom (buffer=buffer@entry=0x7ffff7e204d8 <tcache_key>, length=length@entry=8, flags=flags@entry=1) at ../sysdeps/unix/sysv/linux/getrandom.c:28
内容的提问来源于stack exchange,提问作者CasseroleBoi
相关产品推荐
相关产品推荐

