Memory management/leak?

J

James Sadlier

I'm writing a windows service, that does some stuff every second in a loop,
generating random numbers. It works fine apart from the fact that for some
reason it's using an extra 8K of memory every loop. I've isolated it down to
the use of the Random object. When I remove the use of this object my
service's memory usage stays static.

Any idea what's going wrong? Random doesn't implement IDisposable, so I
can't call Finalize() or Dispose() on it. Nullifying the object doesn't seem
to be cleaning it up, and I don't want to go calling GC.Collect() all the
time.

The code basically looks like this:

while(true)
{
DoStuff();
Thread.Sleep(1000);
}

....

private void DoStuff()
{
//if I remove the next two lines the problem goes away
Random myRandomObject = new Random(DateTime.Now.Millisecond);
myRandomObject = null;

/* some other work*/
}


Any thoughts?
 
J

Jon Skeet [C# MVP]

Any thoughts?

Apart from anything else, it's not a good idea to use Random like that.
Create one instance, and then use that everywhere. You might want to
use one instance per thread, admittedly - though I'd just put some
locking around each call.

Not sure why it should guzzle up memory though - I can't reproduce your
results on a small test basis. Do you have a short but complete program
which demonstrates the problem? See
http://www.pobox.com/~skeet/csharp/complete.html for what I mean.
 
T

Tom Hall

I even took a look at the decompiled code for Random and DateTime (using
Lutz Roeder's .NET Reflector).
Nothing in there that would hang onto objects. Random does create a seed
array of 56 elements - then its just a bunch of math and array operations to
determine next pseudo-random number.

Also, the empty constructor Random() calls Environment.TickCount internally
(which is Native code). I suspect this might be a bit faster and create
less garbage than you calling DateTime.Now.Millisecond as DateTime.Now
creates a new DateTime object whereas Environment.TickCount is static - so
only one object. Add that to Jon's comments and you should be able to get
the garbage creation done to zero!

Of course the garbage collector won't necessarily kick in unless you
generate a worthwhile amount of garbage (in its opinion).

If you get all the memory back when you call Collect yourself then I don't
think there's anything you can do about it.

Of course the other thing you can do is run your code in a memory profiler.
I personally can recommend SciTech www.scitech.se/memprofiler - I've bought
it and used it to find several annoying memory consuming bugs in my code -
often in places you don't suspect as hanging onto objects - like updating a
GUI.

Hope this helps
Tom
 
R

Roy Fine

James,

Does the 8K per loop increase over a long period of time? You may expect to
see the private bytes increase up to some limit before GC kicks in - and
since you have declared that you don't want to control the when for GC, you
pretty much have to llive with the default behavior.

If the privates bytes for your service goes well beyond the value
corresponding to 2/3 of the physical memory on the machine, then you have a
problem, else thats just .Net doing to work for you.

As for the following line of code:
myRandomObject = null;

Take it out - it does nothing good, and only serves as noise. If it is a
long time between iterations of the loop, then the 8K is nothing to worry
about. If it is a short time, then the next iteration the original object
no longer has a reference - which is exactly what you are attempting with
the null assignment.

Creating the Random object in the thread and using it once is bad - you are
not getting a stream of random numbers, you are just getting the first value
from the stream every time (albeit based on a new seed value). These pseudo
random algorithms are scrutinized rather closely for randomness over a
rather large set for an arbitrary seed. I know of no works that has looked
at the distribution of 'n' sets of size 1 with a non-random seed (the
milliseconds is an *ok* seed, but it is not random over the range)

regards
roy fine
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top