我正在与一位同事讨论关于lock_guard的问题,他提出lock_guard可能比Mutex :: lock()/ Mutex :: unlock()慢一些,原因是实例化和取消了类lock_guard的成本。
然后,我创建了一个简单的测试,令人惊讶的是,使用lock_guard的版本几乎比使用互斥锁:: lock()/互斥锁:: unlock()的版本快两倍。
#include <iostream>
#include <mutex>
#include <chrono>
std::mutex m;
int g = 0;
void func1()
{
m.lock();
g++;
m.unlock();
}
void func2()
{
std::lock_guard<std::mutex> lock(m);
g++;
}
int main()
{
auto t = std::chrono::system_clock::now();
for (int i = 0; i < 1000000; i++)
{
func1();
}
std::cout << "Take: " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - t).count() << " ms" << std::endl;
t = std::chrono::system_clock::now();
for (int i = 0; i < 1000000; i++)
{
func2();
}
std::cout << "Take: " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - t).count() << " ms" << std::endl;
return 0;
}
我的机器上的结果:
Take: 41 ms
Take: 22 ms
有人可以弄清楚为什么以及怎么可能吗?
2
您进行了多少次测量?
—
artm
请发布您的编译器标志...基准测试将取决于优化级别...
—
Macmade
专家提示:在进行此类测量时,请交换订单以确保不仅仅是导致问题的冷数据/指令:coliru.stacked-crooked.com/a/81f75a1ab52cb1cc
—
NathanOliver
在进行这样的测量时,另一件有用的东西:将整个事情放在一个更大的循环中,这样就可以运行整个测量集,例如每次运行20次。通常,以后的测量将是实际上有意义的测量,因为到那时,高速缓存已经解决了长期可能发生的任何行为。
—
Mark Phaedrus,
即使
—
弗朗索瓦·安德列
std::lock_guard
速度稍慢,除非您可以证明它对性能至关重要,否则速度的提高不会使使用std::lock_guard
(主要是RAII)的其他好处无效。如果g++
将来有可能抛出的东西或可能会变得更复杂的东西,您几乎必须使用某种对象来拥有锁。