【问题标题】:Should I use nested blocks to improve performance我应该使用嵌套块来提高性能吗
【发布时间】:2016-12-02 16:26:42
【问题描述】:

我一直在学习堆栈和堆,尤其是堆栈及其 LIFO 方法。

这是否适用于方法中的嵌套块,可以用于提高性能,例如

public void Test() {
    int i = 5;
    // do something with i

    int j = 5;
    // do something with j
}

在这个例子中,只有在方法结束时 i 和 j 才会从堆栈中释放出来。

以下会更有效吗? (我知道这是一个简单的过程.....)或者释放的努力会比节省堆栈的大小更多吗?

public void Test() {
    {
        int i = 5;
        // do something with i
    }
    {
        int j = 5;
        // do something with j
    }
}

这仅用于示例目的,我知道我可以重构它等等。我只对方法中的内存发生什么感兴趣......

【问题讨论】:

    标签: .net stack


    【解决方案1】:

    堆栈是为整个方法调用分配的。

    在一些微妙的情况下,添加额外的块可能会有所帮助,就捕获的变量而言 - 如果您有两个 lambda 表达式,其中一个捕获 i,另一个捕获 j ,那么在您的第一种情况下,您最终会得到一个捕获两个变量的合成类,而在第二种情况下,您最终会得到两个类......至少在当前实现中。

    如果没有变量捕获,JIT 至少有可能注意到您一次只使用一个变量,并优化为两个变量重用相同的堆栈空间。

    像这样的微优化很少会对性能产生重大影响,但它们可能会产生非常重大的可读性影响...所以我只会在以下情况下开始降低您的代码的可读性:

    • 您已经进行了可靠的性能测试
    • 您心中有一个具体的绩效目标(这样您就知道什么时候完成了)
    • 您已经缩小了瓶颈所在
    • 您已经证明,降低可读性可以显着提高性能

    【讨论】:

      【解决方案2】:

      假设发布构建/配置,编译器(可能是 JIT 编译器而不是 C# 编译器)应该能够确定变量的生命周期不重叠,因此(如果它选择这样做)编译器可以为两者重用相同的位置(实际上可能是一个寄存器而不是任何特定的堆栈空间)。

      如果这些是引用,并且仍然假设释放,那么您的假设也不成立 - JIT 和 GC 协作以了解变量的生命周期,因此可以在变量的同时收集对象引用它仍然是“在范围内”,前提是该变量实际上没有被再次读取。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-14
        • 2013-08-11
        • 2018-11-02
        • 1970-01-01
        • 2013-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多