Using Objects from another class to decrease Mem Usage

  • Thread starter Thread starter Fish
  • Start date Start date
F

Fish

I have been researching the correct way to organize my solution so that it
makes best use of VB.NET inherent ability to manage resources such as
objects. My solution contains 2 projects and the main problem is that the
mem usage continues to grow until the Service stops responding. I have
received advice to:

"create those objects at a class level; instantiate them when the service
starts, and dispose of them when the service ends. Then include only the
[object handling] code in the timer's elapsed event handler"

This seems simple enough, although I need further clarification. Would it
be best to put the Objects in the Objcls.vb NEW event and FINALIZE event, or
should they be created and finalized in the code class from where they are
being used?

Thanks for your help, a brief example would be appreciated.

Tom
 
Fish said:
I have been researching the correct way to organize my solution so
that it makes best use of VB.NET inherent ability to manage resources
such as objects. My solution contains 2 projects and the main
problem is that the mem usage continues to grow until the Service
stops responding. I have received advice to:

The point is, you should use resources only when you need them and
release those resources as soon as possible. The recommendation to use
Dispose is only useful for objects that implement IDisposable, which
means objects that have access to unmanaged resources.

So if you access files, for example, create the FileStream object *just*
before you write the data, and then call Dispose *immediately* after you
have finished writing the data. Don't hold the FileStream object for
longer than you need to.

IDisposable has no effect on the memory usage if your resources are
entirely managed:

// IDisposable is pointless on this class
class Test : IDisposable
{
int[] data = new int [1000000];
void Dispose()
{
// cannot call 'dispose' on data
}
// other stuff
}

When a Test object is no longer used (not 'reachable') then it is a
candidate for the GC to release its memory, but you have no control when
this will happen.
"create those objects at a class level; instantiate them when the
service starts, and dispose of them when the service ends. Then
include only the [object handling] code in the timer's elapsed event
handler"

As you have stated it, this is very bad advice. You say your problem is
memory, and so creating the objects when the service starts and
disposing them when it ends means that the objects live all the time the
service lives - they are long lived and take up memory all of that time.
Plus the 'advice' of 'dispose when the service ends' is completely
wrong - if they have a Dispose method this means they should be disposed
as soon as possible, so you should not wait until the service ends.

Instead, the objects should only be created just before they are needed
and then disposed just after they have been used. In some cases it could
be argued that such an object could be created, *one* method called,
then disposed (this is how COM+ objects work and .NET single call client
activated remote objects work).

The only time when you want to have a long lived object is when the
initialization of the object takes a long time. But this is not the
problem you are reporting.
This seems simple enough, although I need further clarification. Would
it be best to put the Objects in the Objcls.vb NEW event and
FINALIZE event, or should they be created and finalized in the code
class from where they are being used?

This is bad advice in general. Ignore it.

You should profile your code. For example, use perf mon to look at
memory usage. Identify the code that allocates memory, and reduce those
memory allocations. The Test class above uses a lot of memory, the first
thing to do is to see if it really is necessary to use 1000000 items. If
it is, then adjust your usage of the object:

class App
{
Test test = new Test();// this now has a lifetime of the entire
process
static void Main()
{
App a = new App();
a.Run();
}
void Run()
{
DoSomething(test);
DoSomethingWithoutTest();
}
}

Here, if the GC runs after DoSomething it will not touch the test
object. An improvement would be:

void Run()
{
test = new Test(); // this now has a lifetime of the entire process
DoSomething(test);
test = null; // this allows the test object to be GC'd
DoSomethingWithoutTest();
}

Here, you are making the test object 'unreachable' so if the GC decides
to work after DoSomething it can free up the memory used by the test
object.

A much better solution in this case is not to use an instance field at
all, but create the object just for the specific use:

void DoSomething()
{
Test test = new Test(); //allocate memory
// use test here
test = 0; // just in case GC runs after this point, make test
'unreachable'
// other work that does not use test
} // test is automatically 'unreachable' here

Richard
 
Thanks for the reply, very good stuff. I got my component disposing
quite nicely now as a result.
 
Back
Top