?
Solved

string object not being release

Posted on 2010-11-29
19
Medium Priority
?
336 Views
Last Modified: 2012-05-10
Hello
This is probably a stupid question but how can I release the memory without calling gc.collect()
The code bellow uses  800MB of memory when we click on button1, button2 doesn't seem to release anything, event after 5 minutes, (in release compilation)

Public Class Form1
    Dim l() As String
    Dim s = 10000

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim i
        ReDim l(s)
        l(0) = "fkdnm"
        For i = 1 To s - 1
            l(i) = l(i - 1) & "fkdnmvgd"
        Next
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim i
        For i = 0 To s - 1
            l(i) = ""
            l(i) = Nothing
        Next
        l = Nothing
        'GC.Collect(2)
    End Sub
End Class

Yes, I know I should use stringbuilder
Thanks

Louis
0
Comment
Question by:Atomica
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 4
  • 3
  • +2
19 Comments
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 34230582
How are you determining that it isn't releasing the memory? Also calling the GC from ASP.Net is generally a bad idea.
0
 

Author Comment

by:Atomica
ID: 34230612
Well task manager reports 800MB for this process when button1 is clicked, drops next to nothing as soon as gc.collect is called
0
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 34230688
Ah, ok. You've fallen into the classic trap of thinking that Task Manager is actually showing you how much memory is being used....it isn't, it is showing the Working Set, which isn't the same thing.

If you want to see a more accurate memory usage figure then you need to be looking at the Virtual Memory column in Task Manager or at the process\private bytes and process\virtual bytes in performance monitor.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Atomica
ID: 34230859
Ok, I included

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        MsgBox("VM:" & System.Diagnostics.Process.GetCurrentProcess.PrivateMemorySize64 / 1024 / 1024 & vbNewLine & "PM:" & System.Diagnostics.Process.GetCurrentProcess.PrivateMemorySize64 / 1024 / 1024)
    End Sub

Which shows used memory (GB)
But then again, no change when I click on button2
0
 

Author Comment

by:Atomica
ID: 34230867
BTW, I'm using CLR 2.0 in windows 2003 SBS
0
 
LVL 70

Expert Comment

by:Éric Moreau
ID: 34230885
The memory is not automatically reclaimed by the .Net framework. running GC.Collect uses resources and it is only run when memory is required by the OS.

in your button 2, if you have only this, you can see that most memory is freed:
        l = Nothing
        GC.Collect()
0
 

Author Comment

by:Atomica
ID: 34231092
Ok so if were to saturate my memory with another process, the gc would reclaim the memory. I will try that and let you know.

Is the gc smart enought to release objects with circular references to each others?
0
 
LVL 70

Expert Comment

by:Éric Moreau
ID: 34231345
>>Ok so if were to saturate my memory with another process, the gc would reclaim the memory. I will try that and let you know.

yes.

>>Is the gc smart enought to release objects with circular references to each others?

yes.
0
 

Author Comment

by:Atomica
ID: 34231477
I started  this sample application about 7 times, until my os started paging memory on disk

The initial process still shows 1.2GB of used VM

of course, if I start gc.collect, then the memory is release, any hypothesis?
0
 
LVL 70

Expert Comment

by:Éric Moreau
ID: 34231888
because Windows does not really shows what is in memory, what has been cached to disk, ... you cannot really follow it. Windows itself determines when it should put memory pressure (and then call gc.collect).

your job is to release your objects as soon as you can and let Windows manage what's left.
0
 

Author Comment

by:Atomica
ID: 34232174
But how can I make windows release the memory, I know its ease as putting l=nothing but Id like to see the memory used by the process go down without calling gc.collect
0
 
LVL 70

Expert Comment

by:Éric Moreau
ID: 34232356
you have to call gc.collect.

Windows postpone this operation the further it can because it can be a costly operation.
0
 
LVL 18

Accepted Solution

by:
deighton earned 2000 total points
ID: 34237650
do you know about the different generations of memory in .net?  

data starts off at generation zero, if it falls out of use then there are many level 0 garbage collections to reclaim that memory, if it is still in use it is promoted to level 1 garbage - level 1 garbage collection occurs less often.  Items surviving level 1 garbage collection go to level 2.  

Longest lived items end up as level 2 garbage, level 2 garbage collection occurs least often.  

I would recommend running performance monitor and looking at the .net CLR memory counters, look at the size of the heaps and the numbers of garbage collections occurring.

In your case you are generating a large array of increasingly large strings (as testing I guess).  The effect of this increased memory hit is probably to trigger first level 0 garbage collection, and very likely level 1 garbage collection.  Since your array object is still live during your loop, it very likely ends up as level 2 garbage.  Level 2 garbage is longer lived, you can't collect it without waiting for, or inducing, a level 2 garbage collection.  

.net tunes itself to decide when to call garbage collection.  Microsoft does not recommend inducing garbage collection, it can be detrimental to performance by affecting performance tuning parameters.

Note that when a system is under high memory usage, level 2 garbage collection frequency should increase.  

When I have tried experiments like yours, I often notice that a second execution of the test code triggers the garbage from the previous run to be collected.

Are you experiencing problems with out of memory exceptions, or are you just keen to 'clean up'.  If the latter, then leave .net to do that, do not make a problem if you do not have on.  Saying that I researched this stuff because we had memory problems!










0
 
LVL 18

Expert Comment

by:deighton
ID: 34237666
BTW, setting objects to nothing is now considered obsolete in .net - it too can be counter productive.  Your array goes out of scope when the page events are finished, and that alone is enough to render it collectable.

I agree though that the object=nothing was needed in your case before gc.collect, in that case.   Generally do not set objects to nothing, check that scope is no more than necessary and call dispose methods where provides, or create disposable objects with 'USING'
0
 

Author Comment

by:Atomica
ID: 34269425
Deigthon, what you said is very interesting, I indeed have a out of memory in my webapplication, Im using large shared datasets
I my logic, I do set outdated object to nothing, but the gc doesn't seem to reclaim them except when calling gc.collect, I dont want to use gc.collect as everyone is calling it the "devil"

Their is probably more than on source of problems in my code, but understanding when the GC is called is the my first objective and why I did this sample application.
In IIS 6, the application just restarted when out of memory exception occured, but in IIS7, it sometimes freezes completely without restarting

No so long ago, my search was to target event handler that would hold object in memory but now with gc.collect collecting, I will think of something else

I my test, I started 6 or 7 instance of the sample application, I can't believe that CLR would start paging memory on disk instead of calling gc.collect, as if disk paging was more efficient than calling gc.collect

I will look into using "using"
0
 
LVL 18

Assisted Solution

by:deighton
deighton earned 2000 total points
ID: 34281627
Dataset memory is not reclaimed until the garbage collector does it for you.
Other than gc.collect, I believe there is no other way to speed dataset memory reclaim.  

Have you examined the CLR performance counters?  how much cached data do you have?  Does the amount of memory taken by the managed heaps dip when a level 2 garbage collection occurs or is induced with gc.collect.  Have you checked that there are not live references to objects you no longer need, because these can keep them alive.

Maybe you are caching too much data - are you holding them in the system cache.  Is this to avoid database retrieval overheads?  Is the data global between users, or is it specific to users.  Cached dataset are expensive in memory I have found.

If you can access data using a datareader instead of a dataset, or use SQL to reduce the size of the datasets, that can cut application server memory hit.

0
 

Author Comment

by:Atomica
ID: 34303466
when I call gc.collect, it collects almost everything but my question remains, why is gc.collect not collecting, my object are not live since they disapear when manually calling gc.collect, I find it strange the CLR starts paging or calling a "out memory excpetion" instead of freing up memory.

Apart from timing, is there a difference between calling gc.collect(2) manually and the CLR calling it for you?
0
 
LVL 29

Expert Comment

by:Kumaraswamy R
ID: 34479020
This question has been classified as abandoned and is being closed as part of the Cleanup Program.  See my comment at the end of the question for more details.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article discusses the ASP.NET AJAX ModalPopupExtender control. In this article we will show how to use the ModalPopupExtender control, how to display/show/call the ASP.NET AJAX ModalPopupExtender control from javascript, how to show/display/cal…
IntroductionWhile developing web applications, a single page might contain many regions and each region might contain many number of controls with the capability to perform  postback. Many times you might need to perform some action on an ASP.NET po…
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
Suggested Courses

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question