At least when it comes to instantiating objects.
Even in today’s environment, when the typical amount of RAM on each server is in the gigabytes, it’s still wise to pay attention to memory usage. As a developer or architect, you need to be aware of the trade-offs between eager instantiation and lazy instantiation. Yes, it’s rather pointless to consider an Int16 versus an Int32 for a variable if it’s just going to be created and used a few times in the lifetime of your application. However, if that same variable is instantiated thousands of times or more, then the potential improvement in either memory usage or performance (whichever is more important to you) is definitely worth a look.
Eager/Lazy Instantiation Defined
With eager instantiation, the object is created as soon as possible:
Example – Eager Instantiation
public class Customer { // eager instantiation private Address homeAddress = new Address(); public Address HomeAddress { get { return homeAddress; } } }
With lazy instantiation, the object is created as late as possible:
Example – Lazy Instantiation
public class Customer { private Address homeAddress; public Address HomeAddress { get { // Create homeAddress if it’s not already created if (homeAddress == null) { homeAddress = new Address(); } return homeAddress; } } }
Eager/lazy instantiation also applies to classes, singletons, etc. The principles and potential advantages/disadvantages are similar. For this article, I am only discussing the instantiation of class members.
CPU Cycles vs. Memory Usage
Eager vs. lazy instantiation is the classic performance/memory trade-off. With eager instantiation, you gain some performance improvement at the cost of system memory. Exactly what kind of performance/memory trade-off are we talking about? The answer depends mostly on the objects themselves:
Calculating the Memory Footprint of an Object
According to my own experiments (using DevPartner Studio and .NET Memory Profiler), each reference-type object (class) has a minimum memory footprint of 12 bytes. To calculate the total memory footprint of each reference-type object, add up any other memory used by members in the object. To get the exact memory footprint, you also need to take into consideration “boundaries” but for our purpose that’s probably not important.
The memory foot-print of an object can be closely approximated using the following table (from MSDN Magazine):
| Type | Managed Size in Bytes |
| System.Boolean | 1 |
| System.Byte | 1 |
| System.Char | 2 |
| System.Decimal | 16 |
| System.Double | 8 |
| System.Single | 4 |
| System.Int16 | 2 |
| System.Int32 | 4 |
| System.Int64 | 8 |
| System.SByte | 1 |
| System.UInt16 | 2 |
| System.UInt32 | 4 |
| System.UInt64 | 8 |
Using the example Customer class above, let’s say that each Address object take up 1 KByte, and my application frequently needs to instantiate up to 10,000 Customer objects. Just by creating 10,000 Customer objects, we would need about 10 Megabytes of memory. Now let’s say that the HomeAddress member is only needed when the user drills down into the details of a Customer, and we are looking at a potential saving of 10 Megabytes of memory by using lazy instantiation on HomeAddress.
Memory Usage Can Also Impact Performance
Another important consideration with .NET managed code is garbage collection. In .NET managed code, memory usage has a hidden impact on performance in terms of the work the garbage collector has to perform to recover memory. The more memory you allocate and throw away, the more CPU cycles the garbage collector has to go through.
Recommendations
Additional Reading
Rediscover the Lost Art of Memory Optimization in Your Managed Code
To list available contexts: kubectl config get-contexts To show the current context: kubectl config current-context…
kubectl exec -it <podname> -- sh To get a list of running pods in the…
# Create a soft symbolic link from /mnt/original (file or folder) to ~/link ln -s…
git config --global user.name "<your name>" git config --global user.email "<youremail@somewhere.com>" Related Commands Show current…
TypeScript/JavaScript function getLastMonday(d: Date) { let d1 = new Date(d.getFullYear(), d.getMonth() + 1, 0); let…
I had to do some SMTP relay troubleshooting and it wasn't obvious how to view…