Reputation: 11
I have a Windows Service. There are 2 projects; the Service project (C#) which houses the service class that has all the timer based code (OnStart, OnStop, Timer_Elapsed etc.) and config files. The other project (VB) has the code on what the service actually does in Manager class.
This windows service has memory leaks and the rate of increase in memory usage is ~50 MB/day. In a month, its memory usage reaches almost 1.5 GB.
Long term, my company plans to implement IDisposable but as a temporary solution we decided to use GC.Collect(). So I added GC.Collect() in timer_elapsed() which is called every 3 seconds since poll_interval = 3. I also set some objects which do not implement IDisposable to null/Nothing.
int counter = 0;
private void Timer_Elapsed()
{
// create instance of Manager.cs
try
{
// do something
}
catch (Exception ex)
{
// handle errors
}
finally
{
Process currentProcess = Process.GetCurrentProcess();
Logger logger = LogManager.GetCurrentClassLogger();
logger.Debug("Working Set " + currentProcess.WorkingSet64);
counter += 1;
if (counter == counterThreshold)
{
counter = 0;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
logger.Debug("GC");
logger.Debug("Gen 0: " + GC.CollectionCount(0));
logger.Debug("Gen 1: " + GC.CollectionCount(1));
logger.Debug("Gen 2: " + GC.CollectionCount(2));
}
currentProcess.Dispose();
logger = null;
// set objects to null
_timer.Start();
}
}
When counterThreshold is set to 1, memory usage always stays ~28 MB. When it is set to 10, usage stays ~28 MB +/- 0.5 MB. When it is set to 75 (because when poll_interval = 3, timer_elapsed called 20 times/min, so setting counterThreshold to 75 means calling GC.Collect() every 3.75 minutes), I can see that GC.Collect() does not seem to be making much difference.
12:53:24|SVC.Service1|Working Set 27172864
12:53:27|SVC.Service1|Working Set 27762688
12:53:30|SVC.Service1|Working Set 27844608
12:53:33|SVC.Service1|Working Set 27926528
12:53:36|SVC.Service1|Working Set 28012544
12:53:39|SVC.Service1|Working Set 28094464
12:53:42|SVC.Service1|Working Set 28176384
12:53:45|SVC.Service1|Working Set 28258304
12:53:48|SVC.Service1|Working Set 28344320
12:53:52|SVC.Service1|Working Set 28426240
12:53:55|SVC.Service1|Working Set 28516352
12:53:58|SVC.Service1|Working Set 28598272
12:54:01|SVC.Service1|Working Set 28676096
12:54:04|SVC.Service1|Working Set 28762112
12:54:07|SVC.Service1|Working Set 28839936
12:54:10|SVC.Service1|Working Set 28921856
12:54:13|SVC.Service1|Working Set 29003776
12:54:16|SVC.Service1|Working Set 29089792
12:54:19|SVC.Service1|Working Set 29179904
12:54:22|SVC.Service1|Working Set 29257728
12:54:25|SVC.Service1|Working Set 29343744
12:54:28|SVC.Service1|Working Set 29425664
12:54:31|SVC.Service1|Working Set 29503488
12:54:34|SVC.Service1|Working Set 29536256
12:54:37|SVC.Service1|Working Set 29618176
12:54:40|SVC.Service1|Working Set 29696000
12:54:43|SVC.Service1|Working Set 29777920
12:54:46|SVC.Service1|Working Set 29859840
12:54:49|SVC.Service1|Working Set 29945856
12:54:52|SVC.Service1|Working Set 30081024
12:54:55|SVC.Service1|Working Set 30162944
12:54:58|SVC.Service1|Working Set 30248960
12:55:01|SVC.Service1|Working Set 30330880
12:55:04|SVC.Service1|Working Set 30416896
12:55:07|SVC.Service1|Working Set 30511104
12:55:10|SVC.Service1|Working Set 30597120
12:55:13|SVC.Service1|Working Set 30674944
12:55:16|SVC.Service1|Working Set 30756864
12:55:19|SVC.Service1|Working Set 30842880
12:55:22|SVC.Service1|Working Set 30924800
12:55:25|SVC.Service1|Working Set 31002624
12:55:28|SVC.Service1|Working Set 31064064
12:55:31|SVC.Service1|Working Set 31158272
12:55:34|SVC.Service1|Working Set 31240192
12:55:37|SVC.Service1|Working Set 31318016
12:55:40|SVC.Service1|Working Set 31395840
12:55:43|SVC.Service1|Working Set 31547392
12:55:46|SVC.Service1|Working Set 31543296
12:55:49|SVC.Service1|Working Set 31543296
12:55:53|SVC.Service1|Working Set 31547392
12:55:56|SVC.Service1|Working Set 31543296
12:55:59|SVC.Service1|Working Set 31490048
12:56:02|SVC.Service1|Working Set 31494144
12:56:05|SVC.Service1|Working Set 31490048
12:56:08|SVC.Service1|Working Set 31494144
12:56:11|SVC.Service1|Working Set 31494144
12:56:14|SVC.Service1|Working Set 31494144
12:56:17|SVC.Service1|Working Set 31490048
12:56:20|SVC.Service1|Working Set 31494144
12:56:23|SVC.Service1|Working Set 31543296
12:56:26|SVC.Service1|Working Set 31547392
12:56:29|SVC.Service1|Working Set 31547392
12:56:32|SVC.Service1|Working Set 31547392
12:56:35|SVC.Service1|Working Set 31551488
12:56:38|SVC.Service1|Working Set 31543296
12:56:41|SVC.Service1|Working Set 31543296
12:56:44|SVC.Service1|Working Set 31543296
12:56:47|SVC.Service1|Working Set 31547392
12:56:50|SVC.Service1|Working Set 31543296
12:56:53|SVC.Service1|Working Set 31543296
12:56:56|SVC.Service1|Working Set 31547392
12:56:59|SVC.Service1|Working Set 31547392
12:57:02|SVC.Service1|Working Set 31547392
12:57:05|SVC.Service1|Working Set 31547392
12:57:08|SVC.Service1|Working Set 31547392
12:57:08|SVC.Service1|GC
12:57:08|SVC.Service1|Gen 0: 3
12:57:08|SVC.Service1|Gen 1: 2
12:57:08|SVC.Service1|Gen 2: 2
12:57:11|SVC.Service1|Working Set 31956992
12:57:14|SVC.Service1|Working Set 31956992
12:57:17|SVC.Service1|Working Set 31956992
12:57:20|SVC.Service1|Working Set 31952896
12:57:23|SVC.Service1|Working Set 31952896
12:57:26|SVC.Service1|Working Set 31956992
12:57:29|SVC.Service1|Working Set 31899648
12:57:32|SVC.Service1|Working Set 31903744
12:57:35|SVC.Service1|Working Set 31899648
12:57:38|SVC.Service1|Working Set 31903744
12:57:41|SVC.Service1|Working Set 31903744
12:57:44|SVC.Service1|Working Set 31903744
12:57:47|SVC.Service1|Working Set 31903744
12:57:50|SVC.Service1|Working Set 31903744
12:57:53|SVC.Service1|Working Set 31899648
12:57:56|SVC.Service1|Working Set 31903744
12:57:59|SVC.Service1|Working Set 31899648
12:58:02|SVC.Service1|Working Set 31903744
12:58:05|SVC.Service1|Working Set 31903744
12:58:08|SVC.Service1|Working Set 31903744
12:58:11|SVC.Service1|Working Set 31903744
12:58:14|SVC.Service1|Working Set 31903744
12:58:17|SVC.Service1|Working Set 31899648
12:58:20|SVC.Service1|Working Set 31899648
12:58:23|SVC.Service1|Working Set 31903744
12:58:26|SVC.Service1|Working Set 31903744
12:58:29|SVC.Service1|Working Set 31903744
12:58:32|SVC.Service1|Working Set 31899648
12:58:35|SVC.Service1|Working Set 31899648
12:58:38|SVC.Service1|Working Set 31903744
12:58:42|SVC.Service1|Working Set 31903744
12:58:45|SVC.Service1|Working Set 31899648
12:58:48|SVC.Service1|Working Set 31903744
12:58:51|SVC.Service1|Working Set 31899648
12:58:54|SVC.Service1|Working Set 31903744
12:58:57|SVC.Service1|Working Set 31899648
12:59:00|SVC.Service1|Working Set 31903744
12:59:03|SVC.Service1|Working Set 31903744
12:59:06|SVC.Service1|Working Set 31903744
12:59:09|SVC.Service1|Working Set 31899648
12:59:12|SVC.Service1|Working Set 31903744
12:59:15|SVC.Service1|Working Set 31899648
12:59:18|SVC.Service1|Working Set 31907840
12:59:21|SVC.Service1|Working Set 31899648
12:59:24|SVC.Service1|Working Set 31899648
12:59:27|SVC.Service1|Working Set 32026624
12:59:30|SVC.Service1|Working Set 32030720
12:59:33|SVC.Service1|Working Set 32026624
12:59:36|SVC.Service1|Working Set 32030720
12:59:39|SVC.Service1|Working Set 32030720
12:59:42|SVC.Service1|Working Set 32030720
12:59:45|SVC.Service1|Working Set 32071680
12:59:48|SVC.Service1|Working Set 32067584
12:59:51|SVC.Service1|Working Set 32104448
12:59:54|SVC.Service1|Working Set 32108544
12:59:57|SVC.Service1|Working Set 32108544
13:00:00|SVC.Service1|Working Set 32112640
13:00:03|SVC.Service1|Working Set 32124928
13:00:06|SVC.Service1|Working Set 32202752
13:00:09|SVC.Service1|Working Set 32280576
13:00:12|SVC.Service1|Working Set 32362496
13:00:15|SVC.Service1|Working Set 32473088
13:00:18|SVC.Service1|Working Set 32559104
13:00:21|SVC.Service1|Working Set 32641024
13:00:24|SVC.Service1|Working Set 32722944
13:00:27|SVC.Service1|Working Set 32747520
13:00:30|SVC.Service1|Working Set 32747520
13:00:33|SVC.Service1|Working Set 32690176
13:00:36|SVC.Service1|Working Set 32632832
13:00:39|SVC.Service1|Working Set 32636928
13:00:42|SVC.Service1|Working Set 32628736
13:00:45|SVC.Service1|Working Set 32665600
13:00:48|SVC.Service1|Working Set 32669696
13:00:51|SVC.Service1|Working Set 32669696
13:00:54|SVC.Service1|Working Set 32669696
13:00:54|SVC.Service1|GC
13:00:54|SVC.Service1|Gen 0: 6
13:00:54|SVC.Service1|Gen 1: 4
13:00:54|SVC.Service1|Gen 2: 4
13:00:57|SVC.Service1|Working Set 32673792
13:01:00|SVC.Service1|Working Set 32677888
13:01:03|SVC.Service1|Working Set 32673792
13:01:06|SVC.Service1|Working Set 32677888
13:01:09|SVC.Service1|Working Set 32677888
13:01:12|SVC.Service1|Working Set 32673792
13:01:15|SVC.Service1|Working Set 32677888
13:01:18|SVC.Service1|Working Set 32677888
13:01:21|SVC.Service1|Working Set 32673792
13:01:24|SVC.Service1|Working Set 32673792
13:01:27|SVC.Service1|Working Set 32673792
13:01:30|SVC.Service1|Working Set 32673792
13:01:33|SVC.Service1|Working Set 32628736
13:01:36|SVC.Service1|Working Set 32632832
13:01:39|SVC.Service1|Working Set 32624640
13:01:42|SVC.Service1|Working Set 32628736
13:01:45|SVC.Service1|Working Set 32628736
13:01:48|SVC.Service1|Working Set 32628736
13:01:52|SVC.Service1|Working Set 32628736
13:01:55|SVC.Service1|Working Set 32628736
And when counterThreshold is set to 28800 (i.e. call GC.Collect() once a day) increase in memory usage is still ~50 MB/day and calling GC.Collect() seems to have made no difference at all.
Every time I call GC.Collect(), I expect memory usage to drop to ~28 MB whether I call it continuously or once a day.
Upvotes: 1
Views: 347
Reputation: 10035
Copied from my comment under the question:
GC.Collect does not solve memory leak issues. It does not destroy objects that are alive / referenced by others. GC.Collect only collects objects in given generations. If you believe you have some objects that can immediately be collected, e.g. a big bitmap that has been closed, calling GC.Collect would help. Otherwise, GC.Collect wouldn't do much.
Furthermore, the fact is garbage collection is running constantly in the background. Calling GC.Collect
only forces garbage collection to run now. If there's nothing to collect, memory usage won't drop.
Once per day not works vs run continuously works might be coincidental, that by the time GC.Collect
is called once per day, there's nothing to collect, versus running continuously increases the chance of having things to collect.
Upvotes: 1