linux上执行memcpy,发现将A 拷贝到 B,时间很稳定,约40纳秒,立即执行将B拷贝到A,时间不稳定,有时40纳秒,有时超过500纳秒。我执行代码是绑核了的,不存在代码在不同核上运行;也做了核隔离,不存在其他线程运行在这个核上。
Order *old_order;
Order order;
long long t1 = ::get_current_nano_second(); //封装的clock_gettime函数
::memcpy(&order, old_order, sizeof(Order)); //第一次memcpy
//Reserver1是一个int字段
//old_order->Reserve1 = order.Reserve1; //这一句注释、不注释进行了对比测试
long long t2 = ::get_current_nano_second();
::memcpy(old_order, &order, sizeof(Order)); //第二次memcpy
long long t3 = ::get_current_nano_second();
::memcpy(old_order, &order, sizeof(Order)); //第三次memcpy
long long t4 = ::get_current_nano_second();
注释Reserver1的赋值语句,执行结果:
第一次copy:耗时稳定在30到40纳秒。
第二次copy:耗时波动大,要么在30到40纳秒,要么超过500纳秒。
第三次copy:耗时稳定在30到40纳秒。
不注释掉Reserver1的赋值语句,执行结果:
第一次copy:耗时波动大,要么在30到40纳秒,要么超过500纳秒。
第二次copy:耗时稳定在30到40纳秒。
第三次copy:耗时稳定在30到40纳秒。
从上面的结果来看,似乎第一次写的old_order的时候,执行时间边长。我推测是缓存未命中。old_order的内存可以保证只有当前核会访问。
现在的问题是:难道这么巧,在进行第一次复制,读Cache命中;第二次复制时,写cache miss。我也看了缓存一致性协议MESI,但这个主要是解决不同CPU之间的一致性问题。我的程序运行在Intel i9上,L1、L2是每个核独有的,L3是所有核共享。我实在想不通。
单独看代码片段, old order 并没有初始化,第一次拷贝相当于从某个未知地址拷贝点东西到了 order
回到耗时这个问题,你需要先明白,这个代码片段里面最耗时的地方是变量初始化,需要申请内存,在纳秒级别,申请内存属于很费时的操作
第一次 order 已经申请好了内存,因为你写的代码是 Order order,属于堆,自动申请了内存
后面两次,C 用的不多,不会提示访问非法地址吗?
你试着把 old order 也改成对象,别用指针,再去测延迟,应该是三次拷贝的延迟都一样