4

是否应该使用 if 语句来帮助堆栈的内存释放?

示例 A:

        var objectHolder = new ObjectHolder();
        if (true)
        {
            List<DefinedObject> objectList;
            using (var sr = new GenericStreamReader<DefinedObject>())
            {
                objectList= sr.Get().ToList();
            }
            if (true)
            {
                var DOF = new DefinedObjectFactory();
                objectHolder.DefinedObjects = DOF.DefineObjects(objectList);
            }
        }
        //example endpoint

示例 B:

        var objectHolder = new ObjectHolder();
        List<DefinedObject> objectList;
        using (var sr = new GenericStreamReader<DefinedObject>())
        {
         objectList= sr.Get().ToList();
        }
        var DOF = new DefinedObjectFactory();
        objectHolder.DefinedObjects = DOF.DefineObjects(objectList);
        //example endpoint

当到达示例端点时,示例 A 在堆栈上的占用空间会比在示例 B 中到达示例端点时更轻吗?

4

5 回答 5

12

首先,基于堆栈的分配系统的全部意义在于您不需要以任何方式对其进行优化。别担心。jitter 完全能够意识到永远不会再读取或写入本地,并且如果它认为这是最好的做法,则可以重新使用其存储。让抖动发挥作用;它不需要你的帮助。(*)

而是编写程序,使局部变量对读者有意义。这就是你应该优化的。

最后,永远不需要说“if (true) { }”来引入新的作用域。只需引入一个新范围。完全合法的说法是:

void M()
{
    { // new scope
    }

    { // another one
    }
} 

(*) 在某些情况下,jitter 需要您的帮助,那就是 local 引用堆上的一个对象,该对象包含将由非托管代码使用的资源。抖动不知道非托管代码将使用对象的资源,并且可能会决定没有人再使用该对象并尽早清理它。然后,对象的终结器可能会在非托管代码使用资源时释放终结器线程上的资源!一个对象不能仅仅因为一个局部变量持有它而保证活着。如果局部变量不再被读取,那么抖动可以重新使用它的存储并告诉垃圾收集器收集引用的对象是安全的,这可能会使非托管代码崩溃。您可以使用KeepAlive来提示特定对象需要保持活动状态而不被优化掉的抖动。

于 2012-04-04T00:12:24.903 回答
7

if(true)将在优化构建中编译出来(变量寿命短于整个方法的唯一构建)-因此您建议的两个版本之间绝对没有区别。

于 2012-04-03T23:33:27.903 回答
5

根据用法,我假设DefinedObjectFactory是一个类,而不是一个结构。因此,堆栈上唯一的东西是对DefinedObjectFactory. 实际对象在堆上,由垃圾收集器控制。

您可能节省的唯一堆栈空间是单个指针的空间,因此不值得。

于 2012-04-03T23:48:50.233 回答
1

即使这确实有所作为,我认为您很可能担心的是错误的事情。堆栈空间分配真的是您的应用程序的问题吗?

一般来说,为了微优化而在代码中做“聪明”的事情通常是不值得的。以最干净和最直接的方式编写代码通常是一个更好的主意。之后,如果你发现你确实有一些性能/可扩展性问题(基于做实际测量),你可以选择重写/优化瓶颈部分。

大多数时候,您会发现代码的干净/直接/可读版本执行得很好。如果没有,问题可能不在您认为的地方。

于 2012-04-03T23:40:34.597 回答
0

关于取消分配和垃圾收集,您只能保证一件事 - 它会在某个阶段发生。

正如其他人所说,你的 if(true) 唯一能实现的就是被 Jitter 优化。

您已经在使用 using(..) { } 模式,因此我将重构您的代码以支持这一点,而不是使用 if(true) 块:

if (true)
{
   var DOF = new DefinedObjectFactory();
   objectHolder.DefinedObjects = DOF.DefineObjects(objectList);
}

到:

using (var DOF = new DefinedObjectFactory())
{
   objectHolder.DefinedObjects = DOF.DefineObjects(objectList);
}

看看这是否有帮助。

您可以尝试另一种方法,但绝对不建议将其用于生产代码,因为您不应该抢占内存管理器,但这只是添加一个调用

GC.Collect();

当你退出你的街区。

我认为它不会有帮助,但它可能会向您展示为什么通常不值得担心范围和取消分配。

于 2012-04-03T23:41:54.657 回答