与在外部声明时相比,在临界区块内声明变量是否会对性能产生影响?

时间:2014-08-24 17:16:51

标签: c++ multithreading visual-c++ gcc critical-section

假设有如下所示的代码

void func1()     // first way
{
    CRITICALSECTIONTYPE CS;
    ENTERCRITICALSECTION(CS);
    int x = getValue();
    LEAVECRITICALSECTION(CS);
}
void func2()    // second way
{
    int x;
    CRITICALSECTIONTYPE CS;
    ENTERCRITICALSECTION(CS);
    x = getValue();
    LEAVECRITICALSECTION(CS);
}

与第二种方式相比,第一种方式是否有任何(甚至是最轻微的)性能开销可能性?有什么特定的编译器优化它? 使用汇编代码首选答案。谢谢:))

1 个答案:

答案 0 :(得分:2)

当然答案可能是编译器依赖的。

但是,我编写了一个程序,其中包含一个循环和一个在临界区创建的块变量。然后我通过在循环外创建变量来重新编译它。

  • 生成的汇编代码(MSVC13,未优化的调试模式)对于 单元化变量 非常相同。实际上,编译器在函数入口处生成所需堆栈空间的保留,因此在进入临界区时无需执行任何操作。

我在你的问题上尝试了一些变化:

  • 使用 初始化变量 ,编译器会生成其他初始化指令,您可以将其放入代码中,可能位于关键部分。

  • 在自动存储中使用 未初始化的动态数组 (例如:char y[n];),原则是相同的:不会有其他指令关键部分。为什么这样 ?因为标准只有在大小(此处为n)不变时才接受这些动态数组。同样,在代码生成时,编译器知道在函数入口处在堆栈上分配了多少空间。

  • 如果需要调用 构造函数 ,对于更复杂的对象,则必须在临界区中执行相应的指令。

无论如何,请记住,即使在临界区添加代码,优化器仍然可以找到优化它的方法(例如:常量传播,检测循环不变量等)。

<强> 修改

根据您的要求,这里是第一个案例的ASM代码摘录。很抱歉这个大屏幕截图,但它是唯一能轻松显示代码比较的方法。差异以黄色和灰色突出显示。

您会注意到差异只是与C ++源相对应的注释,以及使用b的行(sollely,因为堆栈偏移被命名为_b$1用于块变量和{{1}用于函数变量)。 (1)堆栈偏移以访问变量(2)函数中的入口点(3)局部变量初始化的示例(4)临界区中的变量(左侧变量在区域内部,右侧外部创建)。

enter image description here