.NETGURU
Setting objects to Nothing uses less memory!
Messages   Related Types
This message was discovered on microsoft.public.dotnet.framework.performance.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.
Post a new message to this list...

Ivan
I have noticed in a lot of code samples that people are using the
SomeObject = Nothing line. But I couldn't find a definitive answer
anywhere to, does this make a difference, or is it a throwback to VB6.

So I have decided to write a little test application.

There are two buttons, the first one assigns 10 megs worth of objects
without setting anything to Nothing.

The second button also assigns 10 megs worth of objects, but when it
is done, it sets everything to nothing.

The code for the first button:
Dim bigObjects() As ReallyBigObject
bigObjects = Array.CreateInstance(GetType(ReallyBigObject), 1000)
'This should chew about 10 megs!
Dim i As Integer
For i = 0 To bigObjects.Length - 1
bigObjects(i) = New ReallyBigObject
Next
'Now do nothing, let the garbage collector pick up the fact that
there are no references
'to these objects

Code for the second button:
Dim bigObjects() As ReallyBigObject
bigObjects = Array.CreateInstance(GetType(ReallyBigObject), 1000)
'This should chew about 10 megs!
Dim i As Integer
For i = 0 To bigObjects.Length - 1
bigObjects(i) = New ReallyBigObject
Next
'Now set these objects to null to see if it makes any difference
to the garbage collector.
For i = 0 To bigObjects.Length - 1
bigObjects(i).InternalSetNull()
bigObjects(i) = Nothing
Next
bigObjects = Nothing

And for completeness, the code for ReallyBigObject
Public Sub New()
'Chew some memory
lotsOfData = Array.CreateInstance(GetType(Byte), 10240) '10 KB
Dim i As Integer
For i = 0 To lotsOfData.Length - 1
lotsOfData(i) = CByte(255)
Next
End Sub

Public Sub InternalSetNull()
Dim i As Integer
Dim j As Integer
For i = 0 To lotsOfData.Length - 1
lotsOfData(i) = Nothing
Next
lotsOfData = Nothing
i = Nothing
j = Nothing

End Sub

When I ran this I polled GC.GetTotalMemory(False) and I was shocked
and disillusioned to find that there was a difference.

After clicking the first button repeatedly it managed to use about 60+
Meg of memory before the garbage collector freed some of it. After
clicking the second button repeatedly the Garbage collector actually
kicks in after 20-30 megs, and it manages to free more memory than the
first button.

Does this mean in order to write less memory hungry applications that
we should still set objects to Nothing like in the bad old VB6 days?

Ivan.
Reply to this message...
 
    
Scott M.
In a nutshell, setting an object to nothing generally makes little
difference to not doing it since the object will fall out of scope and be
flagged as "removable" by the GC. By setting an object to nothing, you can
sometimes improve performance because you are flagging the object for the GC
prior to the end of the procedure and so the GC is aware that the object can
be removed before the procedure has finished.

For long involved procedures, setting the object to nothing can be a good
idea, but for shorter, less-involved procedures it may not make any
difference at all.

"Ivan" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Mark
On Thu, 19 Aug 2004 08:40:59 -0400, Scott M. wrote:

[Original message clipped]

That's not true at all. The GC knows at what point in a scope an object is
no longer used, and it becomes available for GC at that point, not at the
end of the scope. By setting the object to null (or Nothing in vb) you're
keeping the object alive LONGER by using it at least 1 line later in the
scope.

Mark
Reply to this message...
 
    
Alvin Bruney [MVP]
[Original message clipped]

That doesn't sound correct to me. The framework is supposed to be
intelligent enough to optimize that line away. I'm not motivated enough to
go check it at the moment so I am not 100% sure, but I am fairly certain
that this is the way it *should work.

--
Regards,
Alvin Bruney
[ASP.NET MVP http://mvp.support.microsoft.com/default.aspx]
Got tidbits? Get it here... http://tinyurl.com/27cok
"Mark" <Click here to reveal e-mail address> wrote in message
news:147h0196ru054.19sj1d3c785uh$.Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Chris Lyon [MSFT] (VIP)
Alvin is right, in most cases the JIT will optimize away the assugnment to null.

Mark, if you read my response to Ivan's questions you'll see there are cases where setting a reference to null is actually beneficial (large member objects that are no longer
needed but the encapsulating object is still alive, for example).

-Chris

[Original message clipped]

--

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this message are best directed to the newsgroup/thread from which they originated.

Reply to this message...
 
    
Scott M.
From the VS.NET MSDN
Library(ms-help://MS.VSCC.2003/MS.MSDNQTR.2004APR.1033/vblr7/html/vakeyNothing.htm):

"When you assign Nothing to an object variable, it no longer refers to any
object instance. If the variable had previously referred to an instance,
setting it to Nothing does not terminate the instance itself. The instance
is terminated, and the memory and system resources associated with it are
released, only after the garbage collector detects there are no active
references remaining."

So, wouldn't it stand to reason that the use of Nothing indicates that the
variable reference to the object should be released? And, it it has been
released, then the GC can collect it?

How could the GC "know" that the object won't be used again by the variable
reference later on in the code? And, if I set a variable reference to, say,
Public, then shouldn't that mean that the variable must remain in memory for
as long as the Public scope indicates? You are saying that a variable
declared with Public can be removed from memory before its scope has run
out?

If what you say is true, then why bother having a Nothing keyword?

"Mark" <Click here to reveal e-mail address> wrote in message
news:147h0196ru054.19sj1d3c785uh$.Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Chris Lyon [MSFT] (VIP)
Hi Scott

I think you're confusing variables/references with actual objects in memory. Setting a variable to null means it no longer points to the object in memory. It does not mean that
the object in memory is now eligible for garbage collection. For example (C# code):

void Foo() {
Object obj = new Object();
Object obj2 = obj;
obj = null; // obj2 still has a reference to the Object in memory
...
}

So your public member variable will point to an object in memory, but can be set to null/Nothing at any time, and the GC will eventually collect it. The GC knows when to collect
an object in memory (not a variable!) when there are no live references to it, regardless of whether variables are accessible or not.

Hope that helps
-Chris

[Original message clipped]

--

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this message are best directed to the newsgroup/thread from which they originated.

Reply to this message...
 
    
Scott M.
[Original message clipped]

I understand the difference between variables/references and objects. But if
there are no more references to an object in memory (because the variable
has been set to Nothing), then the GC can collect it. As it states in MSDN:

"The instance is terminated, and the memory and system resources associated
with it are released, only after the garbage collector detects there are no
active
references remaining."

And one way to get rid of an active reference to an object in memory is to
set the reference = Nothing.

Reply to this message...
 
    
Chris Lyon [MSFT] (VIP)
Yes, that is correct.

[Original message clipped]

--

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this message are best directed to the newsgroup/thread from which they originated.

Reply to this message...
 
    
Scott M.
Which brings me back to my original point...

If I can get rid of an object reference explicitly by setting an object
variable to Nothing, there is a *possibility* that the object will be
collected sooner than if I hadn't explicitly de-referenced it.

I'll admit that in most cases, this isn't necessary or even that helpful,
but everything I've read on the subject states that by explicitly
de-referencing an object instance in methods that have quite a bit more
processing to do, there is a possibility of the GC collecting the
de-referenced object sooner than if the object hadn't been explicitly
de-referenced.

Is this not so?

""Chris Lyon [MSFT]"" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Jon Skeet [C# MVP] (VIP)
Scott M. <Click here to reveal e-mail address> wrote:
[Original message clipped]

It depends on where that variable is set to nothing. If it's a local
variable which provably isn't used later in the code, then setting it
to nothing won't do any good, because the JIT compiler will already
know that the variable shouldn't stop the GC from collecting the
object.

[Original message clipped]

No, it's not so - if the JIT compiler can prove that the local variable
is not used later on in the code, it won't stop the GC from collecting
the object (in release mode).

--
Jon Skeet - <Click here to reveal e-mail address>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Reply to this message...
 
    
Niall
I've read many times that this only happens in release mode, however I think
(though there seems to be no way to be certain) that I have seen this happen
in debug mode.

We have some unit tests that use WeakReferences to catch and diagnose memory
leaks. One particular test was creating an object locally within the test
method and then performing some actions on it. After the actions were
completed, there were a series of checks for the test, but the object itself
was no longer referenced for the rest of the method. Sometimes, the test
would fail, with the newly created object being collected earlier than
expected (ie in the middle of the test). Using a GC.KeepAlive on the object
until the appropriate time seemed to fix the issue.

I suspect (once again, I can't be sure) that the GC may get more aggressive
when there is a lot of memory used and it is getting desperate for some free
space, and hence it turns on this check - running all of our unit tests is a
long and memory intensive operation. I'd be curious to know if this is
correct.

Niall

"Jon Skeet [C# MVP]" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Jon Skeet [C# MVP] (VIP)
Niall <Click here to reveal e-mail address> wrote:
[Original message clipped]

Could you post a short but complete program which demonstrates that?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.

[Original message clipped]

I don't believe so. What was the scope of the variable? If it had
actually gone out of scope (rather than just being no longer used) then
I would imagine it would be collectable. For instance:

object x = ...;

for (int i=0; i < 10; i++)
{
object y = ...;
}

// Stuff here not involving x

I would expect y to not be counted as a GC root by the line of the
comment, but not x.

--
Jon Skeet - <Click here to reveal e-mail address>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Reply to this message...
 
    
Mark
On Wed, 25 Aug 2004 07:14:06 +0100, Jon Skeet [C# MVP] wrote:
[Original message clipped]

You didn't ask me, but here you go:

using System;

class MainClass
{
    static void Main(string[] args)
    {
        object o = new object();
        WeakReference wr = new WeakReference(o);

        Console.WriteLine(o.ToString());
        Console.WriteLine(wr.IsAlive);

        GC.Collect();

        Console.WriteLine(wr.IsAlive);
    }
}

In Debug mode this prints:
System.Object
True
True

In Release mode this prints:
System.Object
True
False

This means that o became eligibile for collection *BEFORE* the method
ended, even though it was still in scope.

Mark
Reply to this message...
 
    
Jon Skeet [C# MVP] (VIP)
Mark <Click here to reveal e-mail address> wrote:
[Original message clipped]

<snip>

That's the problem with posting at 7 in the morning - I wasn't clear at
all. In non-debug environment, o is indeed eligible for collection -
just not in debug. Niall was suggesting (assuming I read his post
correctly) that a variable (still in scope) is becoming eligible for
collection before the method ends *in debug mode*.

--
Jon Skeet - <Click here to reveal e-mail address>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Reply to this message...
 
    
Mark
On Wed, 25 Aug 2004 18:10:05 +0100, Jon Skeet [C# MVP] wrote:
[Original message clipped]

Hmm, yep, Niall did specifically say it happens in debug mode. I missed
that. It actually makes me feel a lot better, I was starting to worry a bit
about you. I was pretty sure you'd said exactly what I proved in previous
discussions. I'll pay more attention next time.

Mark
Reply to this message...
 
    
Jon Skeet [C# MVP] (VIP)
[Just thought of something else]

Niall <Click here to reveal e-mail address> wrote:
[Original message clipped]

Are you actually running the unit tests under a debugger? It's not a
case of whether a program was built in release mode or debug mode which
affects the GC, but whether it's executing under a debugger or not. If
your code is debug code but running without a debugger attached, you'll
see the more aggressive behaviour.

--
Jon Skeet - <Click here to reveal e-mail address>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Reply to this message...
 
    
Niall
The unit tests run without a debugger, as they are performed by an automated
process. I know there are some things in the framework that change behaviour
when you have a debugger attached. However, every time I have seen people
mention the ability to collect objects when references to them have not gone
out of scope of functions has said release mode, not without a debugger
attached. I had hence presumed that they were referring to whether
optimisation was turned on on the build.

Do you know for sure it's to do with the debugger, rather than build
settings? Is this documented somewhere?

As for posting a short but complete demonstration, it's a little difficult.
We have worked around the issue and I don't have a lot of time to create a
new project. It was an intermittent issue, which seemed to support my idea
that it depended on how heavily the GC was pushed - ie: at what point in our
unit test run this particular test was executed. The whole application
itself is not exactly short :P

As for the scope of the variable, it was in the scope of the entire unit
test function. Generally our tests never have more than one scope because
otherwise you cannot be sure your test is actually doing anything. This is
why, at a quick skim, methods without any ifs or loops look like test
methods to my eyes.

Niall

"Jon Skeet [C# MVP]" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Jon Skeet [C# MVP] (VIP)
Niall <Click here to reveal e-mail address> wrote:
[Original message clipped]

I'm 99.9% sure about it, yes. It makes sense - if you haven't got a
debugger attached, you're not going to want to look at the values of
the variables after their last use.

As for being documented - it might be in Richter's book, but I don't
have that to hand. I usually talk about it being "under debug" which is
unfortunately pretty vague :(

> As for posting a short but complete demonstration, it's a little difficult.

Not necessary now, given that I think we now understand it :)

--
Jon Skeet - <Click here to reveal e-mail address>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Reply to this message...
 
    
Scott M.
But what if we are not talking about a local variable?

"Jon Skeet [C# MVP]" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Chris Lyon [MSFT] (VIP)
If we're talking about an instance variable, then there will be a live reference to the object as long as the encapsulating object is alive, regardless of whether or not you use the
inner object. When the outer object is collected, so too will the inner one.

If you find yourself in a situation where an inner object is no longer being used, you may want to consider the Dispose pattern.

-Chris

[Original message clipped]

--

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this message are best directed to the newsgroup/thread from which they originated.

Reply to this message...
 
    
Jon Skeet [C# MVP] (VIP)
Scott M. <Click here to reveal e-mail address> wrote:
> But what if we are not talking about a local variable?

Then if the member variable is effectively useless before the whole
object is likely to become eligible for collection, then yes, setting
it to null/Nothing could improve things. It should usually be seen as a
sign of weak design though - I rarely find that part of an object
becomes useless before the whole thing does.

--
Jon Skeet - <Click here to reveal e-mail address>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Reply to this message...
 
    
Chris Lyon [MSFT] (VIP)
Hi Ivan

I think people often get confused about setting references to null. There is no hard rule that setting things to null will always or never release memory sooner. In your code
snippets, you're demonstrating a good example of when to set things to null/Nothing, but maybe not how you expected.

The key is your InternalSetNull() method. In the first example, you're keeping your ReallyBigObjects references, which in turn keep references to lotsOfData. By setting
lotsOfData to null, you're telling the GC that you no longer need it, but you still want to keep around your ReallyBigObjects. The GC will then collect the lotsOfData arrays when it
performs its next collection, but not necessarily your ReallyBigObjects (since lotsOfData is really where the memory pressure is coming from).

So to sum up, setting instance variables to null has the effect you're expecting (free memory sooner), while setting local variables to null has little effect.

Hope that makes sense!
-Chris

--------------------
[Original message clipped]

--

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this message are best directed to the newsgroup/thread from which they originated.

Reply to this message...
 
 
System.Array
System.Console
System.GC
System.Object
System.WeakReference




ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
Ad


Need Dot Net Interview Questions?
Ask ExamGuru, Inc. for advice and help on Passing .Net Interviews
.Net Projects
Best-of-breed application framework for .NET projects, developed by ExamGuru, Inc. and ExamGuru IT
Free .net Help
Commission ExamGuru, Inc. and his team for your next bespoke software project
FogBUGZ
The only bug tracking system carefully crafted with one goal in mind: helping teams create great software.
Awesome Tools
If you don't know about these, you're missing out... IT Certification Questions
IT Interview Questions
Free Oracle 10g Training
MCSE Boortcamp
Cisco Study Guides
Cheap Study Guides
Exact Questions
Dot Net Interview Questions
Oracle OCP
Cheap Travel
Designer Perfumes - Wholesale Prices
Free Programming Tutorials
 
ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
 Copyright © ExamGuru, Inc. 2001-2006
Contact Us - Terms of Use - Privacy Policy - www.dot-net-guru.com - www.examguru.net - www.oraclesource.net - www.itinterviews.net - www.examguru.net/ITCertification