我一直在学习堆栈和堆,特别是堆栈及其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
}
}
这仅仅是为了示例目的,我知道我可以重构这个等等。我只对方法中的内存会发生什么感兴趣....
答案 0 :(得分:5)
无论如何,堆栈都是为整个方法调用分配的。
是一些微妙的情况,根据捕获的变量,添加额外的块可能有所帮助 - 如果你有两个lambda表达式,其中一个捕获i
,其中一个捕获{ {1}},然后在你的第一种情况下,你最终得到一个合成类,它捕获两个变量,而在你的第二种情况下,你最终得到两个类......至少在当前实现中。
如果没有变量捕获,至少可能 JIT可能会注意到您一次只使用一个变量,并优化为两者重用相同的堆栈空间。
这样的微优化非常罕见,会对性能产生重大影响,但是它们可能会产生非常重要的可读性影响......所以我只会在以下情况下开始使代码的可读性降低: / p>
答案 1 :(得分:0)
假设发布版本/配置,编译器(可能是JIT编译器而不是C#编译器)应该能够确定变量的生命周期不重叠,因此(如果它选择这样做)编译器可以重用相同的位置(实际上可能是寄存器而不是任何特定的堆栈空间)。
如果这些是引用,而且仍然假设发布,那么你的假设也不成立 - JIT和GC协作来理解变量的生命周期,因此可以在变量的同时收集对象引用它仍然是“在范围内”,只要该变量实际上不再被读取。