从几个版本的memcpy的测速过程学习一点底层的东西

本文通过分析不同版本的memcpy实现,包括Linux内核中的实现、经典的C面试写法和glibc的实现,探讨了它们的效率差异。通过实际测试,展示了CPU缓存、指令预取和缺页对性能的影响,揭示了汇编优化在某些场景下的优势。同时,文章指出,单纯依赖memcpy来评估C语言能力并不恰当,应当关注更深层次的底层知识和优化技巧。
摘要由CSDN通过智能技术生成
 

以下有三个版本的memcpy,对于版本3,很多人都很熟悉,它很经典,很多人面试都写这个,可是我不得不说一句,对于类似的问题,最好的回答有两个:一是调用c库,二是使用汇编。用这一类的问题来考察应聘者的c语言能力,真的很菜!如果真的要考察c语言能力,还不如给几个if,switch-case,for语句呢。
版本1.linux内核中的实现,其实glibc也是如此实现的,省略了不少内容,真正的实现很巧妙,将n个字节分为了三部分(前导字节-对齐到页面+页面+后续字节-页面对齐后的游离字节)进行分块拷贝(linux内核是绝对不会卖弄c语言的,基本的底层函数最终为了高效大多数都用汇编):
char *memcpy1(char *to, char *from, size_t n)
{
    long esi, edi;
    int ecx;
    esi = (long)from;
    edi = (long)to;
    asm volatile("rep ; movsl"
        : "=&c" (ecx), "=&D" (edi), "=&S" (esi)
        : "0" (n / 4), "1" (edi), "2" (esi)
        : "memory"
        );
    return to;
}
版本2.memcpy2为经典的C面试者写法:
char *memcpy2(char *dest, char *src, size_t n)
{
        int i = 0;
    while (i < n)
    {
        dest[i] = src[i];
        i ++;
    }
    return dest;

}
版本3.glibc的写法:
...
仅仅这几个memcpy版本,如何确定哪个更高效呢?以下是一个测试的例子,请看例子1。
例子1:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define COUNTS 6000000

long long getcyclenow()
{
    unsigned int h, l;
    long long bs, cc;
    asm("rdtsc /n/t");
    asm("movl %%eax, %0/n/t":"=g"(l));
    asm("movl %%edx, %0/n/t":"=g"(h));
    bs = h;
    cc = (bs << 32)|l;
    return cc;
}
int main(int argc, char **argv)
{
    time_t st0, st1, st2, st3;
    long long l0, l1, l2, l3;
    int i = 0;
    char *src = (char *)calloc(1, 109);
    strcpy(src, "iiiiabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
    char *dest0 = (char *)calloc(1, 109);
    char *dest1 = (char *)calloc(1, 109);
    char *dest2 = (char *)calloc(1, 109);

    l0 = getcyclenow();   
    dest0 = memcpy(dest0, src, 108);
    l1 = getcyclenow();   
    dest2 = memcpy2(dest2, src, 108);
    l2 = getcyclenow();   
    dest1 = memcpy1(dest1, src, 108);
    l3 = getcyclenow();   
    printf("%X/t%X/t%X/n", l1-l0, l2-l1, l3-l2);
   
    memset(dest0, 0, 109);
    memset(dest1, 0, 109);
    memset(dest2, 0, 109);

    st0 = time(NULL);
    for (i = 0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值