问题遇到的现象和发生背景
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是所有核共享。我实在想不通。