背景:
我正在写一个无锁堆栈,我正在努力优化它。
我发现在高度并发的情况下进行测试时,在错过compare_and_exchange操作后添加睡眠会导致更高的吞吐量:
void stack::push(node* n)
{
node old_head, new_head{ n };
n->n_ = nullptr;
if (head_.compare_exchange_weak(old_head, new_head))
return;
for (;;)
{
n->n_ = old_head.n_;
new_head.create_id(old_head);
if (head_.compare_exchange_weak(old_head, new_head))
return;
// testing conditions _never_ reach here, so why does this line make the program slower??
std::this_thread::sleep_for(std::chrono::nanoseconds(5));
// debug break is used to confirm execution never reaches here
__debugbreak();
}
}
(The full code can be found here on GitHub.)
我在compare_exchange失败两次后睡觉 - 第一个实际上是一个load(),除非堆栈为空。听起来不错吧?这是一个简单的优化。但...
这是我没想到的:
添加睡眠代码会导致永远不会运行睡眠代码的情况下的吞吐量显着降低!通过添加__debugbreak确认了这一点。
示例数字:
test conditions:
----------------------
data_count = 1
loop_count = 100000000
thread_count = 1
sleep code commented out
-------------------------------
operations per second: 75357000
operations per second: 74487000
operations per second: 74571000
operations per second: 75357000
operations per second: 75843000
operations per second: 74183000
operations per second: 74822000
operations per second: 74321000
operations per second: 75301000
operations per second: 73991000
with sleep code
-------------------------------
operations per second: 60716000
operations per second: 61031000
operations per second: 61236000
operations per second: 60957000
operations per second: 60808000
operations per second: 60642000
operations per second: 60734000
operations per second: 60661000
operations per second: 60422000
operations per second: 61162000
这是最新版本的Xcode 5.我在使用Visual Studio 2013时也看到了相似的数字差异。
那么,这里发生了什么?为什么在添加永不执行的内容时代码显示的数字显着降低?
答案 0 :(得分:0)
添加睡眠会增加另一个分支。 如果没有睡眠,如果compare_exchange_weak为false,则会跳回到循环的顶部。 如果compare_exchange_weak为真,则会有一个分支到函数结尾的分支,并且在睡眠之后无条件跳转到循环的顶部。