lin*_*xer 3 c performance glibc
我正在阅读源代码glibc2.9.阅读该strcpy函数的源代码,性能不如我预期的那么好.
以下是strcpyin 的源代码glibc2.9:
char * strcpy (char *dest, const char* src)
{
reg_char c;
char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);
const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;
size_t n;
do {
c = *s++;
s[off] = c;
}
while (c != '\0');
n = s - src;
(void) CHECK_BOUNDS_HIGH (src + n);
(void) CHECK_BOUNDS_HIGH (dest + n);
return dest;
}
Run Code Online (Sandbox Code Playgroud)
因为我不知道使用偏移量的原因,所以我通过将上面的代码与以下代码进行比较来进行一些性能测试:
char* my_strcpy(char *dest, const char *src)
{
char *d = dest;
register char c;
do {
c = *src++;
*d++ = c;
} while ('\0' != c);
return dest;
}
Run Code Online (Sandbox Code Playgroud)
结果,strcpy在我的测试中表现更差.我删除了有关绑定指针的代码.
为什么glibc版本使用偏移?
以下是关于测试的介绍.
gcc test.c.我使用的测试代码如下:
#include <stdio.h>
#include <stdlib.h>
char* my_strcpy1(char *dest, const char *src)
{
char *d = dest;
register char c;
do {
c = *src++;
*d++ = c;
} while ('\0' != c);
return dest;
}
/* Copy SRC to DEST. */
char *
my_strcpy2 (dest, src)
char *dest;
const char *src;
{
register char c;
char * s = (char *)src;
const int off = dest - s - 1;
do
{
c = *s++;
s[off] = c;
}
while (c != '\0');
return dest;
}
int main()
{
const char str1[] = "test1";
const char str2[] = "test2";
char buf[100];
int i;
for (i = 0; i < 10000000; ++i) {
my_strcpy1(buf, str1);
my_strcpy1(buf, str2);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用该my_strcpy1功能时,输出为:
[root@Lnx99 test]#time ./a.out
real 0m0.519s
user 0m0.517s
sys 0m0.001s
[root@Lnx99 test]#time ./a.out
real 0m0.520s
user 0m0.520s
sys 0m0.001s
[root@Lnx99 test]#time ./a.out
real 0m0.519s
user 0m0.516s
sys 0m0.002s
Run Code Online (Sandbox Code Playgroud)
使用时my_strcpy2,输出为:
[root@Lnx99 test]#time ./a.out
real 0m0.647s
user 0m0.647s
sys 0m0.000s
[root@Lnx99 test]#time ./a.out
real 0m0.642s
user 0m0.638s
sys 0m0.001s
[root@Lnx99 test]#time ./a.out
real 0m0.639s
user 0m0.638s
sys 0m0.002s
Run Code Online (Sandbox Code Playgroud)
我知道这个命令不太准确time.但我可以从用户时间得到答案.
更新:
To remove the cost used to calculate the offset, I removed some code and added a global variable.
#include <stdio.h>
#include <stdlib.h>
char* my_strcpy1(char *dest, const char *src)
{
char *d = dest;
register char c;
do {
c = *src++;
*d++ = c;
} while ('\0' != c);
return dest;
}
int off;
/* Copy SRC to DEST. */
char *
my_strcpy2 (dest, src)
char *dest;
const char *src;
{
register char c;
char * s = (char *)src;
do
{
c = *s++;
s[off] = c;
}
while (c != '\0');
return dest;
}
int main()
{
const char str1[] = "test1test1test1test1test1test1test1test1";
char buf[100];
off = buf-str1-1;
int i;
for (i = 0; i < 10000000; ++i) {
my_strcpy2(buf, str1);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但表现my_strcpy2还是差于my_strcpy1.然后我检查了汇编的代码,但也未能得到答案.
我还扩大了弦的大小和性能my_strcpy1仍然比my_strcpy2
它使用偏移方法,因为这消除了循环中的一个增量 - glibc代码只需要递增s,而你的代码必须增加s和d.
请注意,您正在查看的代码是与体系结构无关的回退实现 - glibc具有覆盖许多体系结构的组件实现(例如x86-64strcpy()).