局部变量和垃圾生成

Fad*_*adi 2 c#

有一段我的代码被重复调用(每秒2000+).为了避免垃圾生成并降低性能开销,我将所有局部变量都移到了类级别,但我不确定这种方法是否有效......

我的问题是......

  • 当垃圾收集器收集局部变量时?
  • 将局部变量移动到类级别是否会提高性能并减少垃圾生成?

Jon*_*eet 14

变量不是垃圾收集的.对象是垃圾收集的......在运行时可以检测到任何实时代码不再引用它们之后,它们可以随时被垃圾收集.这可以包括局部变量引用的对象:

public void Foo()
{
    object x = new object();
    // The object can't be collected here...
    Console.WriteLine(x);
    // But it *can* be collected here
    Console.WriteLine("This line doesn't depend on x");
}
Run Code Online (Sandbox Code Playgroud)

这是非常罕见的好主意,改变垃圾收集着想"自然"的设计......应该说这是方法的状态不是对象的状态通常是自然的一部分,所以把一个局部变量成实例变量通常是个坏主意.

也就是说,我们不知道那些局部变量代表什么,或者它们的任何内容 - 我们需要更多的背景来评论你的具体情况.


Jep*_*sen 3

考虑这个非常简单的示例(其中SomeObject是类,而不是结构):

class C
{
  void MethodCalledMillionsOfTimes()
  {
    var so = new SomeObject();
    // some use of so
  }
}
Run Code Online (Sandbox Code Playgroud)

每次调用该方法时,都会在堆上创建一个新对象。在使用结束一段时间后,需要对其进行垃圾收集。这是每次调用该方法时要收集的一个对象。

那么假设改成:

class C
{
  SomeObject soField;

  void MethodCalledMillionsOfTimes()
  {
    soField = new SomeObject();
    // some use of soField
  }
}
Run Code Online (Sandbox Code Playgroud)

这没有任何改变!您仍然为每个方法调用创建一个新实例。垃圾收集器必须做同样数量的工作。

但如果你这样做了怎么办:

class C
{
  SomeObject soField = new SomeObject();

  void MethodCalledMillionsOfTimes()
  {
    // some use of soField
  }
}
Run Code Online (Sandbox Code Playgroud)

这次,每次在同一实例上再次调用该方法时,都会重复使用同一对象。因此需要垃圾收集的对象更少(假设该方法实际上在同一个C对象上调用了多次)。SomeObject请注意,只有当实例可以多次使用并且每次使用都不会“破坏”其状态时,这才有效。

如果许多线程同时调用该方法,请确保该对象soField可以处理该方法。

如果你进一步说:

class C
{
  static SomeObject soStaticField = new SomeObject();

  void MethodCalledMillionsOfTimes()
  {
    // some use of soStaticField
  }
}
Run Code Online (Sandbox Code Playgroud)

那么的所有实例之间只共享一个对象CSomeObjectGC 无需收集任何信息。

但是,此 GC 活动通常对您的性能并不重要。因此,请衡量它对于您的情况是否重要。