Chinaunix首页 | 论坛 | 博客
  • 博客访问: 36704
  • 博文数量: 7
  • 博客积分: 156
  • 博客等级: 入伍新兵
  • 技术积分: 150
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-20 20:16
文章分类

全部博文(7)

文章存档

2011年(7)

分类: C/C++

2011-06-02 12:54:44

做了一个字符串拷贝的性能分析,结果有点出人意料
strcpy_by_char 是按字符一个一个拷贝
strcpy_align 是按照CPU的取址宽度拷贝
memcpy做两次,证明函数调用顺序对函数的性能没有太大影响
拷贝的空间为堆上32M内存

不做优化,基本符合预期
memcpy > memmove > strcpy > strcpy_aligin > strcpy_by_char
rabbithan@SRV44_28_sles10:~/data/codes/mem/str$ gcc -o str -O0 str.c
rabbithan@SRV44_28_sles10:~/data/codes/mem/str$ ./str 33554432
memcpy time = 19
strcpy_by_char time = 173
strcpy_align time = 69
strcpy time = 66
memmove time = 27
memcpy time = 19

O2优化,注意memcpy的性能反而下降了。。。,同时gcc的优化让自定义函数的性能超过了系统函数strcpy
rabbithan@SRV44_28_sles10:~/data/codes/mem/str$ gcc -o str -O2 str.c
rabbithan@SRV44_28_sles10:~/data/codes/mem/str$ ./str 33554432
memcpy time = 27
strcpy_by_char time = 35
strcpy_align time = 26
strcpy time = 66
memmove time = 27
memcpy time = 27


独立测试几个系统函数,拷贝的大小仍然是32M,结果基本相同
rabbithan@SRV44_28_sles10:~/data/codes/mem/memcpy$ gcc -o mem -O0 mem.c
rabbithan@SRV44_28_sles10:~/data/codes/mem/memcpy$ ./mem
strcpy time = 67
memmove time = 28
memcpy time = 19

rabbithan@SRV44_28_sles10:~/data/codes/mem/memcpy$ gcc -o mem -O2 mem.c
rabbithan@SRV44_28_sles10:~/data/codes/mem/memcpy$ ./mem
strcpy time = 66
memmove time = 28
memcpy time = 28


/************************str.c************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

static void strcpy_by_char(char *dst, char *src) {
if (dst != NULL && src != NULL) {
while (*src != '\0') {
*dst++ = *src++;
}
}
}

static void strcpy_align(char *dst, char *src) {
int n = 0;

if (dst != NULL && src != NULL) {
for (;;) {
if (src[0] == '\0') {
n = 0;
} else if (src[1] == '\0') {
n = 1;
} else if (src[2] == '\0') {
n = 2;
} else if (src[3] == '\0') {
n = 3;
} else {
n = 4;
}
if (n >= 3) {
*(uint32_t *) dst = *(uint32_t *) src;
dst += 4;
src += 4;
} else if (n == 0) {
*dst++ = *src++;
} else if (n == 1) {
*dst++ = *src++;
*dst++ = *src++;
} else if (n == 2) {
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
}
if (n < 4) {
break;
}
}
}
}

int main(int argc, char **argv) {
char *dst = NULL, *src = NULL, *p = NULL;
struct timeval stv, etv;
int i, len;

if (argc > 1) {
len = atoi(argv[1]);
} else {
len = 4 * 1024 * 1024;
}

dst = (char *) malloc(len);
src = (char *) malloc(len);
memset(src, 0, len);
if (dst != NULL && src != NULL) {
p = src;
for (i = 0; i < len - 1; i++) {
*p++ = i % 10 + 0x30;
}
*p++ = '\0';
if (len < 128) {
printf("src = %s\n", src);
}

memset(dst, 0, len);
gettimeofday(&stv, NULL);
memcpy(dst, src, len);
gettimeofday(&etv, NULL);
printf("memcpy time = %lu\n", (etv.tv_sec - stv.tv_sec) * 1000 + (etv.tv_usec - stv.tv_usec) / 1000);

memset(dst, 0, len);
gettimeofday(&stv, NULL);
strcpy_by_char(dst, src);
gettimeofday(&etv, NULL);
printf("strcpy_by_char time = %lu\n", (etv.tv_sec - stv.tv_sec) * 1000 + (etv.tv_usec - stv.tv_usec) / 1000);
if (strcmp(src, dst) != 0) {
printf("strcpy_by_char fail\n");
}

memset(dst, 0, len);
gettimeofday(&stv, NULL);
strcpy_align(dst, src);
gettimeofday(&etv, NULL);
printf("strcpy_align time = %lu\n", (etv.tv_sec - stv.tv_sec) * 1000 + (etv.tv_usec - stv.tv_usec) / 1000);
if (strcmp(src, dst) != 0) {
printf("strcpy_align fail\n");
}

memset(dst, 0, len);
gettimeofday(&stv, NULL);
strcpy(dst, src);
gettimeofday(&etv, NULL);
printf("strcpy time = %lu\n", (etv.tv_sec - stv.tv_sec) * 1000 + (etv.tv_usec - stv.tv_usec) / 1000);
if (strcmp(src, dst) != 0) {
printf("strcpy fail\n");
}

memset(dst, 0, len);
gettimeofday(&stv, NULL);
memmove(dst, src, len);
gettimeofday(&etv, NULL);
printf("memmove time = %lu\n", (etv.tv_sec - stv.tv_sec) * 1000 + (etv.tv_usec - stv.tv_usec) / 1000);
if (strcmp(src, dst) != 0) {
printf("memmove fail\n");
}

memset(dst, 0, len);
gettimeofday(&stv, NULL);
memcpy(dst, src, len);
gettimeofday(&etv, NULL);
printf("memcpy time = %lu\n", (etv.tv_sec - stv.tv_sec) * 1000 + (etv.tv_usec - stv.tv_usec) / 1000);
if (strcmp(src, dst) != 0) {
printf("memcpy fail\n");
}
}

exit(EXIT_SUCCESS);
}

/************************mem.c************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define MEM_SIZE (32 * 1024 * 1024)

static char dst[MEM_SIZE];
static char src[MEM_SIZE];

int main(int argc, char **argv) {
struct timeval stv, etv;
char *p = NULL;
int i, len;

len = MEM_SIZE;
memset(src, 0, len);
p = src;
for (i = 0; i < len - 1; i++) {
*p++ = i % 10 + 0x30;
}
*p++ = '\0';

memset(dst, 0, len);
gettimeofday(&stv, NULL);
strcpy(dst, src);
gettimeofday(&etv, NULL);
printf("strcpy time = %lu\n", (etv.tv_sec - stv.tv_sec) * 1000 + (etv.tv_usec - stv.tv_usec) / 1000);

memset(dst, 0, len);
gettimeofday(&stv, NULL);
memmove(dst, src, len);
gettimeofday(&etv, NULL);
printf("memmove time = %lu\n", (etv.tv_sec - stv.tv_sec) * 1000 + (etv.tv_usec - stv.tv_usec) / 1000);

memset(dst, 0, len);
gettimeofday(&stv, NULL);
memcpy(dst, src, len);
gettimeofday(&etv, NULL);
printf("memcpy time = %lu\n", (etv.tv_sec - stv.tv_sec) * 1000 + (etv.tv_usec - stv.tv_usec) / 1000);

exit(EXIT_SUCCESS);
}
阅读(2404) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~