我正在阅读的源代码。在阅读函数的源代码时,它的性能并不如我所期望的那样好。
以下是中的源代码:
作为结果,我的测试表明
为什么
下面是有关测试的介绍:
1. 平台:x86(Intel(R) Pentium(R) 4),gcc 版本 4.4.2
2. 编译标志:没有标志,因为我不想进行任何优化;命令为
我使用的测试代码如下:
当使用
使用
以下是中的源代码:
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;
}
因为我不知道使用偏移量的原因,所以我通过比较上述代码和以下代码进行了一些性能测试:
char* my_strcpy(char *dest, const char *src)
{
char *d = dest;
register char c;
do {
c = *src++;
*d++ = c;
} while ('\0' != c);
return dest;
}
作为结果,我的测试表明
strcpy
的性能较差。我已经删除了有关绑定指针的代码。为什么
glibc
版本要使用偏移量?下面是有关测试的介绍:
1. 平台:x86(Intel(R) Pentium(R) 4),gcc 版本 4.4.2
2. 编译标志:没有标志,因为我不想进行任何优化;命令为
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;
}
当使用
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
使用
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
我知道使用命令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;
}
但是my_strcpy2
的性能仍然不如my_strcpy1
。然后我检查了汇编代码,但也没有得到答案。
我还扩大了字符串的大小,my_strcpy1
的性能仍然优于my_strcpy2
。
strcpy
的 C 版本,你的平台几乎肯定有一个汇编版本,glibc 会使用它。 - Dietrich EppCHECK_BOUNDS_HIGH
宏看起来像是针对调试版本代码(启用“有界指针”支持时)的额外安全检查。在启用这些调试宏的情况下测试性能毫无意义。 - AnT stands with Russia