处理托管对象是否会提高.Net中的性能?

时间:2011-07-08 06:04:36

标签: .net garbage-collection

在托管对象上实现Dispose()也是如此,通过从提示中获取提示来改善垃圾收集器的性能可能会绕过其整个进程。

我在一个没有得到高票的问题上看到answer,但这是真的吗?如果是,那怎么样?

  

没错。我同意Aaronaught的观点。   此外,Microsoft建议在2003年中期的Don Box网络广播中,每个.Net开发人员都应该处理他们自己的对象,无论是托管还是非托管,因为这可以将代码性能提高多达20%。如果做得好,它可以显着改善性能。因此它是每个.net开发人员需要知道和使用的核心技能。

4 个答案:

答案 0 :(得分:6)

你只是不能 Dispose托管内存,就像你可以调用Dispose来释放文件句柄等一样。唯一可以清理托管内存的东西内存是垃圾收集器。

可以使Dispose方法将类中的所有变量都设置为null,希望这会允许垃圾收集器收集所有以前引用的 - 更早的对象 - 但是很少有情况会实际帮助,因为通常你的对象无论如何都有资格收集。它还会使您的代码很多更难以遵循。

在大多数情况下必须担心对象的生命周期的能力是C#的好处之一 - 为什么要通过使每个类实现IDisposable来摆脱它?您真的想要自己管理“所有权”和生命吗?

我怀疑你误解了你在问题中引用的(当然有点不清楚)答案。我不相信它主张处理所有对象 - 我相信它主张明确处理已经实现IDisposable的类型的实例。这与纯托管类型无关,后者几乎从不实现IDisposable

答案 1 :(得分:2)

正如Jon Skeet所指出的,这段代码设计错误:


 public class SomeClass : IDisposable
    {
        private string SomeData;

        public void LoadFileIntoMemory(string filename)
        {
            using (var sr = new StreamReader(filename))
            {
                SomeData = sr.ReadToEnd();
            }
        }
        public void DoSomethingWithDataInMemory()
        {
            //whatever
        }
        public void Dispose()
        {
            SomeData = null;
        }
    }

    class Program
    {
        public static void Main()
        {
            using (var sC = new SomeClass())
            {
                sC.LoadFileIntoMemory("somefile");
                sC.DoSomethingWithDataInMemory();
            }
        }
    }

简单地做这件事要好得多


 public class SomeClass
    {
        private string SomeData;

        public void LoadFileIntoMemory(string filename)
        {
            using (var sr = new StreamReader(filename))
            {
                SomeData = sr.ReadToEnd();
            }
        }
        public void DoSomethingWithDataInMemory()
        {
            //whatever
        }
    }

    class Program
    {
        public static void Main()
        {
            var sC = new SomeClass();
            sC.LoadFileIntoMemory("somefile");
            sC.DoSomethingWithDataInMemory();
            sC = null;
        }
    }

当您的类使用某些资源时,如果类的实例的变量设置为null,则应严格执行IDisposable。将包含实例设置为null(gc运行时)将清除所有受管资源。

答案 2 :(得分:1)

首先,通过调用Dispose方法,它绝不暗示GC应该做任何特殊的事情。与任何其他方法一样,Dispose是一种常规方法。

魔法酱是Dispose所做的,即释放不再需要的资源。

IDisposable对象的#1规则是在完成它们时调用Dispose。是的,GC可能最终清理内存,但如果对象仍然链接到仍在使用的任何其他对象,它们将保留。 Dispose还清理非常重要的非托管资源,例如数据库连接,文件句柄,锁等。这些肯定需要尽快关闭。

简而言之,如果您实例化了一个IDisposable对象,则在完成时将其置弃。

是的,调用Dispose需要花费成本,但正如我之前所说,它意味着对象可以互相取消链接,允许GC在下次运行时释放它们。它还意味着可以立即释放非托管资源。另一场胜利。内存和资源泄漏会导致性能损失,如果应用程序变得过于极端,应用程序就会崩溃!

开发人员可能一直在保护重要资源,所以请不要试图再次猜测他!

分析是你的朋友。如果重新创建这些对象的性能是一个问题,请缓存它们,但仍然准备在完成后处理它们。

答案 3 :(得分:0)

是的,我同意这一点。因为垃圾收集器的工作是使用未使用的组件释放内存,但是它会不时地执行,如果开发人员自己完成这项工作,这将影响性能,因为额外的对象不会留在内存中,尽管它的内存等待垃圾收集器清理。