Using less memory by utilizing lazy instantiation - Hendrik Swanepoel

Hendrik Swanepoel

Using less memory by utilizing lazy instantiation

I often use lazy instantiation in order to keep my memory utilization at an acceptable rate. This is useful especially in scenarios where a hierarchy of objects exists  - meaning composite relationships exists between classes.

To illustrate what I mean, I have devised a little scenario.

We want to write is a system that represents a library - to such an extent that even the paragraphs of text in the books will be represented by objects.


So we will have a few classes:

  • Library
  • Book
  • Page
  • Paragraph

The relationships of these objects are very easy to understand:

  • A library contains many books (and without books isn't truly a library)
  • A book contains many pages (and without pages isn't really a book)
  • A page contains many paragraphs (and without paragraphs can't really be called a page - except if it was written by Terry Pratchett)


The following image uses UML to illustrate this relationship:

It would make sense to:

  • Add a property to the Library class which is a collection of Books instances - all the books belonging to the library
  • Add a property to the Book class which is a collection of Page instances - all the pages belonging to the book
  • Add a property to the Page class which is a collection of Paragraph instances - all the paragraphs belonging to the page

We could put the code to instantiate the collection classes pertaining to each class in the constructors.
This would cause a little problem. Consider this:

  • We have a library with a 1000 books.
  • The books have an average of 200 pages.
  • The pages have an average of 4 paragraphs.

If we were to instantiate this library it will instantiate a 1000 Book objects - even though they might not be referenced by the caller. Maybe the caller just wanted to access the address property of the library.
Each Book object that will be instantiated will instantiate another 200 page objects, which in turn will instantiate another 4 paragraphs. In the end we'll instantiate these objects, although we just wanted to get the address of the library:

  • Library 1
  • Books 1000
  • Pages 200 000
  • Paragraphs 800 000

What would be the correct way to do this? Assuming that we want a property that returns all the child objects for each object, we could use lazy instantiation of the property's value.

For the Library object we'll insert a Books property and a books private variable(which will store the actual value), like this:

        //the private variable which will store the collection of books
        private BookCollection books;
        public BookCollection Books
        {
            get
            {
                //check to see if a value has been assigned to the books variable
                //   if not - set the value 
                if(books == null)
                {
                    books = SetTheBooksCollectionMethod();
                }
                return books;
            }
        }

This way, the collection properties will only be populated on demand, sidestepping the recursive instantiation. So if we want to instantiate the library to retrieve it's address, it will not lead to instantiation of over a million related objects.

Posted: Mar 24 2004, 02:09 PM by hendrik | with 2 comment(s)
Filed under:

Comments

Simon Stewart said:

I haven't used it, but the WeakReference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemweakreferenceclasstopic.asp) object in .NET also looks useful for limiting memory usage.

This could be quite useful for creating a cache, etc...
# March 24, 2004 2:29 PM

Hendrik Swanepoel said:

Thanks, I'll have a look at it!
# April 8, 2004 5:46 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: