+ -
当前位置:首页 → 问答吧 → strcpy VS memcpy, 不看不知道,一看吓一跳

strcpy VS memcpy, 不看不知道,一看吓一跳

时间:2010-08-05

来源:互联网

网上搜了搜,都说memcpy比strcpy快,理论上来说也能说得通。但运行的结果让我大吃一惊。strcpy比memcpy快40%
  1. //g++ -g malloc.c
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <sys/time.h>
  5. #include <string.h>

  6. #define SIZE 128

  7. struct timeval begin, end;
  8. char source[SIZE], destination[SIZE];

  9. void mcp(char* dst, char* src, int len, int num)
  10. {
  11.     for(int i = 0; i<num; i++)
  12.     {
  13.         memcpy(dst, src, len);
  14.     }
  15. }

  16. void strcopy(char* dst, char* src, int num)
  17. {
  18.     for(int i = 0; i<num; i++)
  19.     {
  20.         strcpy(dst, src);
  21.     }
  22. }

  23. int main(int argc, char** argv)
  24. {
  25.     int num;

  26.     if ( argc < 2 )
  27.     {
  28.         printf("usage: %s num\n", argv[0]);
  29.         exit(1);
  30.     }
  31.     num = atoi(argv[1]);

  32.     memset(source, 0x21, sizeof(source));
  33.     source[sizeof(source)-1] = '\0';

  34.     gettimeofday(&begin, NULL);
  35.     mcp(destination, source, 128, 600000);
  36.     gettimeofday(&end, NULL);
  37.     printf("dur: %u seconds, %u micro sec\n", end.tv_sec-begin.tv_sec, end.tv_usec-begin.tv_usec);
  38.    
  39.     gettimeofday(&begin, NULL);
  40.     strcopy(destination, source, 600000);
  41.     gettimeofday(&end, NULL);
  42.     printf("dur: %u seconds, %u micro sec\n", end.tv_sec-begin.tv_sec, end.tv_usec-begin.tv_usec);
  43.     return 0;
  44. }
复制代码
#:~/test$ ./a.out 2
dur: 0 seconds, 64623 micro sec
dur: 0 seconds, 46371 micro sec

作者: mukey   发布时间: 2010-08-05

本帖最后由 ilwmin 于 2010-08-05 17:25 编辑

静待高手解答

作者: ilwmin   发布时间: 2010-08-05

你的程序,我的结果
  1. $ ./a.out 2
  2. dur: 0 seconds, 11797 micro sec
  3. dur: 0 seconds, 64604 micro sec
复制代码

作者: daybreakcx   发布时间: 2010-08-05

测试结果:
[root@localhost test]# ./2 2
dur: 0 seconds, 13710 micro sec
dur: 0 seconds, 62005 micro sec

作者: rain_fish   发布时间: 2010-08-05

03年的ID, 来恶作剧么

作者: phy0077   发布时间: 2010-08-05

我也吓了一大跳。。。。

作者: rain_fish   发布时间: 2010-08-05

不过我这里结果还是memcpy要快一些.快一倍多.

作者: ilwmin   发布时间: 2010-08-05

你for写的不好。

作者: prolj   发布时间: 2010-08-05



QUOTE:
测试结果:
[root@localhost test]# ./2 2
dur: 0 seconds, 13710 micro sec
dur: 0 seconds, 62005 mic ...
rain_fish 发表于 2010-08-05 17:23




嗯,我又看了一下,和优化很有关系,如果编译时用:
#:~/test$ g++ -g -O2 malloc.c
#:~/test$ ./a.out
dur: 0 seconds, 9993 micro sec
dur: 0 seconds, 28225 micro sec

所以,你可以试试g++ -g -O0 malloc.c, 再测测

作者: mukey   发布时间: 2010-08-05



QUOTE:
你for写的不好。
prolj 发表于 2010-08-05 17:27



期待给出源码

作者: mukey   发布时间: 2010-08-05

for(int i = 0; i<num; i++)

int i;
for(i = 0; i<num; i++)

不知道为什么,我这边默认的是C99。C89你的写法也报错,我不知道你怎么编过的。

作者: prolj   发布时间: 2010-08-05

看了一下,memcpy是一字节一字节复制
strcpy是可以四个一次

作者: zliming   发布时间: 2010-08-05

memcpy  strcpy
O0   +
O1                 +
O2                 +
O3   +

作者: zliming   发布时间: 2010-08-05

strcpy代码:
/* Copyright (C) 1992, 1995, 1997, 2002, 2004 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <string.h>

#undef __stpcpy
#undef stpcpy

#ifndef weak_alias
# define __stpcpy stpcpy
#endif

/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST.  */
char *
__stpcpy (dest, src)
     char *dest;
     const char *src;
{
  register char *d = dest;
  register const char *s = src;

  do
    *d++ = *s;
  while (*s++ != '\0');

  return d - 1;
}
#ifdef libc_hidden_def
libc_hidden_def (__stpcpy)
#endif
#ifdef weak_alias
weak_alias (__stpcpy, stpcpy)
#endif
#ifdef libc_hidden_builtin_def
libc_hidden_builtin_def (stpcpy)
#endif


memcpy代码:
/* Copy memory to memory until the specified number of bytes
   has been copied.  Overlap is NOT handled correctly.
   Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   Contributed by Torbjorn Granlund ([email protected]).

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#include <string.h>
#include <memcopy.h>
#include <pagecopy.h>

#undef memcpy

void *
memcpy (dstpp, srcpp, len)
     void *dstpp;
     const void *srcpp;
     size_t len;
{
  unsigned long int dstp = (long int) dstpp;
  unsigned long int srcp = (long int) srcpp;

  /* Copy from the beginning to the end.  */

  /* If there not too few bytes to copy, use word copy.  */
  if (len >= OP_T_THRES)
    {
      /* Copy just a few bytes to make DSTP aligned.  */
      len -= (-dstp) % OPSIZ;
      BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);

      /* Copy whole pages from SRCP to DSTP by virtual address manipulation,
         as much as possible.  */

      PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);

      /* Copy from SRCP to DSTP taking advantage of the known alignment of
         DSTP.  Number of bytes remaining is put in the third argument,
         i.e. in LEN.  This number may vary from machine to machine.  */

      WORD_COPY_FWD (dstp, srcp, len, len);

      /* Fall out and copy the tail.  */
    }

  /* There are just a few bytes to copy.  Use byte memory operations.  */
  BYTE_COPY_FWD (dstp, srcp, len);

  return dstpp;
}
libc_hidden_builtin_def (memcpy)

作者: ilwmin   发布时间: 2010-08-05

  1. __Z3mcpPcS_ii:
  2. LFB21:
  3.         pushl        %ebp
  4. LCFI0:
  5.         movl        %esp, %ebp
  6. LCFI1:
  7.         pushl        %edi
  8. LCFI2:
  9.         pushl        %esi
  10. LCFI3:
  11.         pushl        %ebx
  12. LCFI4:
  13.         movl        16(%ebp), %edx
  14.         movl        20(%ebp), %ebx
  15.         testl        %ebx, %ebx
  16.         jle        L1
  17.         xorl        %eax, %eax
  18.         .p2align 2,,3
  19. L3:
  20.         movl        8(%ebp), %edi
  21.         movl        12(%ebp), %esi
  22.         movl        %edx, %ecx
  23.         rep movsb
  24.         incl        %eax
  25.         cmpl        %eax, %ebx
  26.         jg        L3
  27. L1:
  28.         popl        %ebx
  29. LCFI5:
  30.         popl        %esi
  31. LCFI6:
  32.         popl        %edi
  33. LCFI7:
  34.         leave
  35. LCFI8:
  36.         ret
复制代码
这是GCC生成的那个for memcpy

http://dev.firnow.com/course/3_p ... 00861/118646_4.html
这个是strcpy->strcat的实现

作者: zliming   发布时间: 2010-08-05

现在对我来说讨论这是无用的

作者: chinesedragon   发布时间: 2010-08-05

相关阅读 更多

热门下载

更多