glibc 和相同代码之间的不同性能
Different performance between glibc and same code
我正在开发一个复制字符串的程序。
我检查了性能以与 glibc 进行比较。
我用这个命令下载了 glibc 的源代码:
apt-get source glibc
我比较了下面的代码。
/glibc-2.19/string/strcpy.c
#include<string>
并使用 strcpy()
应该是差不多的表现,我预料...
然而,结果却截然不同。
我尝试了一些 gcc 优化选项,例如 O1
O2
O3
但结果是相似的。
有什么魔法可以提高速度吗?
希望知道原因。
这是代码
// test for performance.
/******************************************************************************/
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stddef.h>
/******************************************************************************/
char *
strcpy_glibc (dest, src)
char *dest;
const char *src;
{
char c;
char *s = (char *) src;
const ptrdiff_t off = dest - s - 1;
do
{
c = *s++;
s[off] = c;
}
while (c != '[=11=]');
return dest;
}
/******************************************************************************/
void test(int iLoop, int iLen,
char *szFuncName, char*(*func)(char *s1, const char *s2))
{
time_t tm1, tm2;
int i;
char s1[512];
char s2[512];
// initialize the test string.
for(i = 0; i < iLen; i++) {
s1[i] = '@';
}
s1[iLen] = '[=11=]';
/**************************************************************************/
printf("test(): %s() started, iLoop = %d, iLen = %d.\n",
szFuncName, iLoop, iLen);
tm1 = time(NULL);
for(i = 0; i < iLoop; i++) {
func(s2, s1);
func(s1, s2);
func(s2, s1);
func(s1, s2);
func(s2, s1);
func(s1, s2);
func(s2, s1);
func(s1, s2);
func(s2, s1);
func(s1, s2);
}
tm2 = time(NULL);
printf("test(): %s() terminated in %d [sec].\n", szFuncName, (int)(tm2 - tm1));
printf("test(): %s() answer s1[0] = %c.\n", szFuncName, s1[0]);
}
/******************************************************************************/
int main(int argc, char *argv[])
{
printf("main(): Started.\n");
test(100000000, 511, "strcpy_glibc", strcpy_glibc);
test(100000000, 511, "strcpy", strcpy);
test(100000000, 511, "strcpy_glibc", strcpy_glibc);
test(100000000, 511, "strcpy", strcpy);
printf("main(): Terminated.\n");
return 0;
}
/******************************************************************************/
/* EOF */
结果就在这里...
************************$ ./strcpy_test_3
main(): Started.
test(): strcpy_glibc() started, iLoop = 100000000, iLen = 511.
test(): strcpy_glibc() terminated in 238 [sec].
test(): strcpy_glibc() answer s1[0] = @.
test(): strcpy() started, iLoop = 100000000, iLen = 511.
test(): strcpy() terminated in 56 [sec].
test(): strcpy() answer s1[0] = @.
test(): strcpy_glibc() started, iLoop = 100000000, iLen = 511.
test(): strcpy_glibc() terminated in 238 [sec].
test(): strcpy_glibc() answer s1[0] = @.
test(): strcpy() started, iLoop = 100000000, iLen = 511.
test(): strcpy() terminated in 55 [sec].
test(): strcpy() answer s1[0] = @.
main(): Terminated.
************************$
嗯,这意味着 strcpy()
比 strcpy_glibc()
快 4 倍,但代码相同。
我很困惑...
您不能直接将 libc 代码复制到应用程序中并期望获得更好的性能,因为 libc 和 OS 有很多特定的代码和内部知识,因此预计会有性能差异。
试试这个:
static __inline__ __attribute__((always_inline))
char * strcpy_glibc(char * __restrict to, const char * __restrict from)
{
char *save = to;
for (; (*to = *from); ++from, ++to);
return(save);
}
如果不频繁调用,请尝试在您的应用程序中使用 inline function
而不是函数指针。肯定会获得更好的性能,但此代码无法处理极端情况和检查。
我正在开发一个复制字符串的程序。 我检查了性能以与 glibc 进行比较。 我用这个命令下载了 glibc 的源代码:
apt-get source glibc
我比较了下面的代码。
/glibc-2.19/string/strcpy.c
#include<string>
并使用strcpy()
应该是差不多的表现,我预料... 然而,结果却截然不同。
我尝试了一些 gcc 优化选项,例如 O1
O2
O3
但结果是相似的。
有什么魔法可以提高速度吗? 希望知道原因。
这是代码
// test for performance.
/******************************************************************************/
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stddef.h>
/******************************************************************************/
char *
strcpy_glibc (dest, src)
char *dest;
const char *src;
{
char c;
char *s = (char *) src;
const ptrdiff_t off = dest - s - 1;
do
{
c = *s++;
s[off] = c;
}
while (c != '[=11=]');
return dest;
}
/******************************************************************************/
void test(int iLoop, int iLen,
char *szFuncName, char*(*func)(char *s1, const char *s2))
{
time_t tm1, tm2;
int i;
char s1[512];
char s2[512];
// initialize the test string.
for(i = 0; i < iLen; i++) {
s1[i] = '@';
}
s1[iLen] = '[=11=]';
/**************************************************************************/
printf("test(): %s() started, iLoop = %d, iLen = %d.\n",
szFuncName, iLoop, iLen);
tm1 = time(NULL);
for(i = 0; i < iLoop; i++) {
func(s2, s1);
func(s1, s2);
func(s2, s1);
func(s1, s2);
func(s2, s1);
func(s1, s2);
func(s2, s1);
func(s1, s2);
func(s2, s1);
func(s1, s2);
}
tm2 = time(NULL);
printf("test(): %s() terminated in %d [sec].\n", szFuncName, (int)(tm2 - tm1));
printf("test(): %s() answer s1[0] = %c.\n", szFuncName, s1[0]);
}
/******************************************************************************/
int main(int argc, char *argv[])
{
printf("main(): Started.\n");
test(100000000, 511, "strcpy_glibc", strcpy_glibc);
test(100000000, 511, "strcpy", strcpy);
test(100000000, 511, "strcpy_glibc", strcpy_glibc);
test(100000000, 511, "strcpy", strcpy);
printf("main(): Terminated.\n");
return 0;
}
/******************************************************************************/
/* EOF */
结果就在这里...
************************$ ./strcpy_test_3
main(): Started.
test(): strcpy_glibc() started, iLoop = 100000000, iLen = 511.
test(): strcpy_glibc() terminated in 238 [sec].
test(): strcpy_glibc() answer s1[0] = @.
test(): strcpy() started, iLoop = 100000000, iLen = 511.
test(): strcpy() terminated in 56 [sec].
test(): strcpy() answer s1[0] = @.
test(): strcpy_glibc() started, iLoop = 100000000, iLen = 511.
test(): strcpy_glibc() terminated in 238 [sec].
test(): strcpy_glibc() answer s1[0] = @.
test(): strcpy() started, iLoop = 100000000, iLen = 511.
test(): strcpy() terminated in 55 [sec].
test(): strcpy() answer s1[0] = @.
main(): Terminated.
************************$
嗯,这意味着 strcpy()
比 strcpy_glibc()
快 4 倍,但代码相同。
我很困惑...
您不能直接将 libc 代码复制到应用程序中并期望获得更好的性能,因为 libc 和 OS 有很多特定的代码和内部知识,因此预计会有性能差异。
试试这个:
static __inline__ __attribute__((always_inline))
char * strcpy_glibc(char * __restrict to, const char * __restrict from)
{
char *save = to;
for (; (*to = *from); ++from, ++to);
return(save);
}
如果不频繁调用,请尝试在您的应用程序中使用 inline function
而不是函数指针。肯定会获得更好的性能,但此代码无法处理极端情况和检查。