您的位置:首页 > 运维架构 > Linux

linux中的strcpy 与 memcpy效率比较

2012-12-03 11:33 295 查看


Linux中strcpy()与memcpy()效率的比较

发表于 2011
年 04 月 02 日 由 admin

优化程序性能时,后知后觉地才发现strcpy()很耗时,特别是与memcpy()相比较。因此查看了一下两个函数的Linux实现源码。

strlen()和strcpy()的实现:

static inline size_t __kernel_strlen(const char *s)

{

const char *sc;

for (sc = s; *sc++; )

;

return sc - s - 1;

}

static inline char *__kernel_strcpy(char *dest, const char *src)

{

char *xdest = dest;

asm volatile ("\n"

"1: move.b (%1)+,(%0)+\n"

" jne 1b"

: "+a" (dest), "+a" (src)

: : "memory");

return xdest;

}

strlen()是C语言实现,逐字节取出字符串的内容,并判断是否为结束标志(0);strcpy()为了提高拷贝效率,使用了汇编语言来实现,基本作法也是逐字节拷贝,直到碰上字符串结束字符(0)。

而Linux内核源码中,可以找到多份不同的memcpy()实现。除了因为内嵌汇编因此必须针对不同处理器平台给出不同实现外,memcpy()还区分了32位系统和64位系统。以下以x86平台32位的一个实现为例:

static __always_inline void *__memcpy(void *to, const void *from, size_t n)

{

int d0, d1, d2;

asm volatile("rep ; movsl\n\t"

"movl %4,%%ecx\n\t"

"andl $3,%%ecx\n\t"

"jz 1f\n\t"

"rep ; movsb\n\t"

"1:"

: "=&c" (d0), "=&D" (d1), "=&S" (d2)

: "0" (n / 4), "g" (n), "1" ((long)to), "2" ((long)from)

: "memory");

return to;

}

为了提高效率,memcpy()也采用了内嵌汇编的作法。但memcpy()充分利用了机器字长为32位的特性(32位系统,一次内存读/写可操作4字节的数据, 对于64位系统,则一次可操作8字节数据)。先按4字节一组(movsl)拷贝,共复制n/4次;对剩下的零头再逐字节拷贝。如果支持,memcpy()还可以使用了MMX/SSE指令增加一次操作中的字节数,进一步提高效率。

比较strcpy()和memcpy()的实现,就知道了对于长符串,为什么strcpy()会消耗数倍于memcpy()的时间。

测算性能用到的几个方法:

1. 多次操作(比如重复100次)累加后再求平均用时

2. x86体系中的RDTSC指令也常被用来获取精确时间(CPU时钟滴哒数),但在多核系统中,由于多核之间的时钟计数存在不同步以及CPU降频运行的可能,因此,Win/Linux平台上,现在已不推荐使用此指令进行精确计时,而代之以clock_gettime()(linux系统)或QueryPerformanceCounter()和QueryPerformanceFrequency()(win系统)。

此条目发表在 C/C++, Unix-like 分类目录,贴了 c, Linux 标签。将固定链接加入收藏夹。

← DDL/DML/DCL/TCL基本概念

数据库的一些基本概念 →


《Linux中strcpy()与memcpy()效率的比较》有 1 条评论


Cnfn 说:

2011 年 12 月 18 日下午 11:27

以前只是听说memcpy效率高,但从没有想到去看看它如何实现的,再次受教
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: