Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Local variables and garbage generation

Tags:

c#

There is a piece of my code which is called repeatedly (2000+ each second). To avoid garbage generation and to reduce performance overhead, I moved all local variables to class level, but I'm not sure if this approach is effective...

My question is...

  • When the local variables are being collected by the garbage collector?
  • Does moving local variables to class level boost performance and reduce garbage generation?
like image 728
Fadi Avatar asked Dec 02 '22 18:12

Fadi


2 Answers

Variables aren't garbage collected. Objects are garbage collected... and they can be garbage collected any time after the runtime can detect that they're no longer referenced by any live code. This can include objects referred to by local variables:

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");
}

It's very rarely a good idea to change a "natural" design for the sake of garbage collection... something which is the state of a method isn't usually naturally part of the state of an object, so turning a local variable into an instance variable is usually a bad idea.

That said, we don't know what those local variables represent, or anything about them - we'll need more context to comment on your specific case.

like image 181
Jon Skeet Avatar answered Dec 04 '22 07:12

Jon Skeet


Consider this very simple example (where SomeObject is a class, not a struct):

class C
{
  void MethodCalledMillionsOfTimes()
  {
    var so = new SomeObject();
    // some use of so
  }
}

Each time the method is called, one new object is created on the heap. It needs to be garbage collected some time after the use of it has ended. That is one object to collect per call of the method.

Then suppose it is changed into:

class C
{
  SomeObject soField;

  void MethodCalledMillionsOfTimes()
  {
    soField = new SomeObject();
    // some use of soField
  }
}

This changes nothing! You still create one new instance for each method call. The garbage collector has to do the same amount of work.

But what if you did:

class C
{
  SomeObject soField = new SomeObject();

  void MethodCalledMillionsOfTimes()
  {
    // some use of soField
  }
}

This time the same object is re-used each time the method is called again on the same instance. So fewer objects need to be garbage collected (assuming the method is actually called many times on the same C object). Note that this can only work if the SomeObject instance can be used many times, and does not have its state "ruined" by each use.

If many threads call the method at once, be sure the object soField can handle that.

If you go further and say:

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

  void MethodCalledMillionsOfTimes()
  {
    // some use of soStaticField
  }
}

then there's only one object shared between all instances of C. No SomeObject will have to be collected by the GC.

However, this GC activity is very often not important for your performance. So please measure if it is important or not in your case.

like image 26
Jeppe Stig Nielsen Avatar answered Dec 04 '22 08:12

Jeppe Stig Nielsen