免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 11890 | 回复: 3
打印 上一主题 下一主题

我的memcpy还是不如标准库的厉害 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-12-28 17:36 |显示全部楼层 |倒序浏览

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <memory.h>

  4. #ifdef WIN32
  5.     #include <windows.h>
  6. #else
  7.     #include<sys/time.h>
  8.     #include<unistd.h>
  9. #endif

  10. double get_time_ms()
  11. {
  12. #ifdef WIN32
  13.     return (double)GetTickCount();
  14. #else
  15.     struct timeval tv;
  16.     struct timezone tz;
  17.     gettimeofday (&tv , &tz);
  18.     return tv.tv_sec * 1000 + tv.tv_usec / 1000 ;
  19. #endif
  20. }

  21. //这是微软公开的crt src文件夹内的源代码:
  22. void * memcpy_1 (void * dst, void * src , size_t n)
  23. {
  24.     void * ret = dst;
  25.     while (n--) {
  26.             *(char *)dst = *(char *)src;
  27.             dst = (char *)dst + 1;
  28.             src = (char *)src + 1;
  29.     }
  30.     return ret;
  31. }


  32. //这是我写的,按照最近流行的优化方式做的
  33. void * memcpy_2 (void * dst, void * src , size_t n)
  34. {
  35.     void * ret = dst;
  36.     size_t l = n>>2;
  37.     while (l--) {
  38.         *(size_t *)dst = *(size_t *)src;
  39.         dst = (size_t *)dst + 1;
  40.         src = (size_t *)src + 1;
  41.     }
  42.     l = n & 3;
  43.     while (l--) {
  44.         *(char *)dst = *(char *)src;
  45.         dst = (char *)dst + 1;
  46.         src = (char *)src + 1;
  47.     }
  48.     return ret;
  49. }

  50. void main(int argc, char ** argv)
  51. {
  52.     const int cstMemSize = 0x2FFFFFF;

  53.     if(argc<2)
  54.     {
  55.         printf("请输入参数 [ 0 | 1 | 2 | 3] ");
  56.         return ;
  57.     }

  58.     char * str  = (char*)malloc(cstMemSize);
  59.     char * str2 = (char*)malloc(cstMemSize+16);

  60.     size_t t1 = get_time_ms();

  61.     switch(argv[1][0])
  62.     {
  63.         case '0': memcpy(str, str2, cstMemSize );
  64.             break;
  65.         case '1': memcpy_1(str, str2, cstMemSize );
  66.             break;
  67.         case '2': memcpy_2(str, str2, cstMemSize );
  68.             break;
  69.         case '3': memcpy_2(str, str2+1, cstMemSize );  //考虑字节不对齐的情况
  70.             break;
  71.     }
  72.    
  73.    
  74.     double t2 = get_time_ms();
  75.     free(str);
  76.     free(str2);
  77.     printf("memset_%c %f\n", argv[1][0] ,t2-t1);

  78. }
复制代码


在windows xp/vc6环境下:

结果发现memcpy_1是最慢的,当然,这是串操作,当然很慢;
但是直接调用memcpy函数是最快的,这大概是微软在vc链接程序时做的优化.
而上面memcpy_2的效果一般般,比memcpy_1快,但是不如直接调用memcpy快.


在gcc/freebsd环境下,如果未加优化参数-O2,case '3'的情况速度更慢.我怀疑可能是字节不对齐带来的恶果.
不过,当开启了-O2后,4个case的测试时间差不多了.但是还是gcc自己的memset函数最快.

我现在怀疑,象(int *)这样的奇技淫巧如果使用不当,带来的效果不明显,还不如不用.现实情况是复杂的,编译器比我考虑的多的多.

论坛徽章:
0
2 [报告]
发表于 2006-12-28 17:48 |显示全部楼层
估计是人家使用了更优化的指令.

论坛徽章:
0
3 [报告]
发表于 2006-12-29 09:05 |显示全部楼层
呵呵,这回真是抛砖引玉了, 引出的玉非常多,我仔细学习下.

论坛徽章:
0
4 [报告]
发表于 2006-12-29 11:04 |显示全部楼层
嗯,看起来的确是这样, MOVSB指令就是为了移动串而生的,用它的确应该快.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP