Using Objects from another class to decrease Mem Usage

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Fish

    Using Objects from another class to decrease Mem Usage

    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



  • Richard Grimes

    #2
    Re: Using Objects from another class to decrease Mem Usage

    Fish wrote:[color=blue]
    > 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:[/color]

    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.
    [color=blue]
    > "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"[/color]

    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.
    [color=blue]
    > 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?[/color]

    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(tes t);
    DoSomethingWith outTest();
    }
    }

    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(tes t);
    test = null; // this allows the test object to be GC'd
    DoSomethingWith outTest();
    }

    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
    --




    Comment

    • Fish

      #3
      Re: Using Objects from another class to decrease Mem Usage

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

      --
      Sent via .NET Newsgroups

      Comment

      Working...