.NET Forum / .NET Framework / Performance / December 2005
Memory Usage - Return Type
|
|
Thread rating:  |
Zeeshan Gulzar - 22 Dec 2005 04:25 GMT Is there any difference in following two codes, regarding memory consumption as well as Performance
ArrayList x = GetArrayList();
ArrayList GetArrayList() { ArrayList b = new ArrayList(); // Store some works in ArrayList b return b; }
-----------------------------------------------------
ArrayList x = new ArrayList() GetArrayList(ref x);
void GetArrayList(ref ArrayList x) { // Store some works in ArrayList x } -----------------------------------------------------
Also, is there any machanism to remove only above ArrayList object from memory explictly when this is no more required. like delete keyword in C++.
Thanks in advance.
Jon Skeet [C# MVP] - 22 Dec 2005 06:28 GMT > Is there any difference in following two codes, regarding memory consumption > as well as Performance [quoted text clipped - 17 lines] > // Store some works in ArrayList x > } Well, the easiest thing to do would be to test it. Note that if you're only adding things to the ArrayList, you don't need to pass x by reference. See http://www.pobox.com/~skeet/csharp/parameters.html
The performance difference, if any, will be tiny. You should always design your classes for readability and maintainability first - only consider micro-optimising performance in this way after you've proved you've got a problem. In this case, returning the ArrayList sounds like the better approach, although it would depend on the exact situation.
> Also, is there any machanism to remove only above ArrayList object from > memory explictly when this is no more required. like delete keyword in C++. No. You *can* call the garbage collector (or at least ask it to run) but it's almost always a bad idea. Just let it get collected in the course of time.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Zvonko Keber - 22 Dec 2005 08:02 GMT The difference would be that in the first example, two objects are created - one "outside" the function (ArrayList x), and the other ArrayList is created inside the GetArrayList. When the function finishes, ArrayList B is copied to the X, and then the reference to the ArrayList B is lost (object still exists, but it's ready for garbage collection).
In the second example, only one object is created: the one inside GetArrayList. And when the function finishes, only reference to the object is returned to the X. Reference to the object is not lost although the function exited and will not be collected during GC. Therefore you saved some little time on copy operation.
Theoretically this could be a problem on huge objects (big arraylists, bitmaps,...) and you should test it before you decide.
The only "delete" would be X = null; This virtually frees up some memory space, bu it actually tells GC to remove it during next garbage collection, and works only for objects.
There are some special cases where you need to delete the object created (for example when working with GDI) but that is usually explicitly well documented.
> Is there any difference in following two codes, regarding memory > consumption [quoted text clipped - 25 lines] > > Thanks in advance. Zvonko Keber - 22 Dec 2005 08:06 GMT Sorry, correction:
In second example, object is created OUTSIDE the function, and therefore there is no copy operation.
> The difference would be that in the first example, two objects are > created - one "outside" the function (ArrayList x), and the other [quoted text clipped - 48 lines] >> >> Thanks in advance. Jon Skeet [C# MVP] - 22 Dec 2005 08:08 GMT > The difference would be that in the first example, two objects are created - > one "outside" the function (ArrayList x), and the other ArrayList is created [quoted text clipped - 10 lines] > Theoretically this could be a problem on huge objects (big arraylists, > bitmaps,...) and you should test it before you decide. Bitmaps and ArrayLists are both reference types - however large they are, there won't be any performance penalty in terms of returning them (whether it's by a return value or an output parameter).
I don't know whether you meant that or just that if the ArrayList doesn't become eligible for GC at some stage, it could be a problem. I'm assuming that the OP does want the ArrayList at the point at which the method returns - after that it's up to him to determine the lifetime of it.
> The only "delete" would be X = null; This virtually frees up some memory > space, bu it actually tells GC to remove it during next garbage collection, > and works only for objects. No, it doesn't tell the GC to remove it. It just means that that particular variable doesn't hold a reference to the object any more. It's very, very rarely worth setting a variable to null for the purposes of garbage collection.
> There are some special cases where you need to delete the object created > (for example when working with GDI) but that is usually explicitly well > documented. That's not actually deleting objects - that's disposing them so they can release unmanaged resources. Calling Dispose does *not* free the memory associated with an object.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Zvonko Keber - 22 Dec 2005 08:48 GMT > Bitmaps and ArrayLists are both reference types - however large they > are, there won't be any performance penalty in terms of returning them [quoted text clipped - 4 lines] > the method returns - after that it's up to him to determine the > lifetime of it. Working with huge objects is much faster if you pass them between functions by reference. Especially when there are many huge objects, and many "passing around".
>> The only "delete" would be X = null; This virtually frees up some memory >> space, bu it actually tells GC to remove it during next garbage [quoted text clipped - 5 lines] > It's very, very rarely worth setting a variable to null for the > purposes of garbage collection. An object becomes eligible for GC once when all it's references are lost (set to null). In Zeeshan's exmaple, once is enough. Also, no matter if the variables are set to null or not, once the function exists all it's objects are ready for GC because there are no more references to them.
Jon Skeet [C# MVP] - 22 Dec 2005 09:08 GMT > > Bitmaps and ArrayLists are both reference types - however large they > > are, there won't be any performance penalty in terms of returning them [quoted text clipped - 8 lines] > by reference. Especially when there are many huge objects, and many "passing > around". I think you misunderstand reference types, or what pasing by reference means. If I create an ArrayList and add a million elements to it, then call a method using a variable with a reference to the ArrayList as a parameter, the only data which is passed is the reference. Note that this is not passing *by* reference.
See http://www.pobox.com/~skeet/csharp/parameters.html
To give a concrete example:
using System; using System.Collections;
class Test { static void Main() { ArrayList al = new ArrayList(); for (int i=0; i < 1000000; i++) { al.Add ("Hello"); } ShowCount(al); } static void ShowCount(ArrayList list) { Console.WriteLine (list.Count); } }
The call to ShowCount here is *not* expensive, and would be no cheaper (actually very slightly more expensive, I believe) if you made "list" a reference parameter instead of a value parameter.
> >> The only "delete" would be X = null; This virtually frees up some memory > >> space, bu it actually tells GC to remove it during next garbage [quoted text clipped - 8 lines] > An object becomes eligible for GC once when all it's references are lost > (set to null). Well, there's a difference between a reference and a variable. There don't need to be any variables involved for an object to still be alive. For instance:
new ArrayList().Add("Hello");
During the call to Add (within subtle limits which I won't go into right now), the object still isn't available for garbage collection, despite there being no actual *variables* with references to the ArrayList.
> In Zeeshan's exmaple, once is enough. Also, no matter if the > variables are set to null or not, once the function exists all it's objects > are ready for GC because there are no more references to them. I assume you meant "exits" rather than "exists" - that confused me for a bit :)
What I assume you really mean is that the local variables and parameters of a method are only used as GC roots while the method is executing.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Zvonko Keber - 22 Dec 2005 09:41 GMT > The call to ShowCount here is *not* expensive, and would be no cheaper > (actually very slightly more expensive, I believe) if you made "list" a > reference parameter instead of a value parameter. Yes, but... :-) Which of these would be more expensive (performance and memory)?
Bitmap bmp = new Bitmap(1000, 1000); for(int y = 0; y<100000; y++) bmp = Replace(bmp); ... static Bitmap Replace(Bitmap b) { Bitmap bmp = b; //do some work with bmp return bmp; } ------------------- OR ------------------- Bitmap bmp = new Bitmap(1000, 1000); for(int y = 0; y<100000; y++) Replace(ref bmp); ... static void Replace(ref Bitmap b) { //do some work with b }
My real-world example is huge and it makes sense, but it comes down to this nonsense of an example.
> new ArrayList().Add("Hello"); > > During the call to Add (within subtle limits which I won't go into > right now), the object still isn't available for garbage collection, > despite there being no actual *variables* with references to the > ArrayList. Okay, but after that particular line, there are no more references to the arraylist, although object is still alive and kicking in memory, but it will be collected during next GC. Together with all string objects inside the arraylist. Right?
>> In Zeeshan's exmaple, once is enough. Also, no matter if the >> variables are set to null or not, once the function exists all it's [quoted text clipped - 3 lines] > I assume you meant "exits" rather than "exists" - that confused me for > a bit :) Yes, sorry :-)
Jon Skeet [C# MVP] - 22 Dec 2005 10:00 GMT > > The call to ShowCount here is *not* expensive, and would be no cheaper > > (actually very slightly more expensive, I believe) if you made "list" a [quoted text clipped - 23 lines] > My real-world example is huge and it makes sense, but it comes > down to this nonsense of an example. Well, there's no point in making the first version return anything. It would be most efficiently (and readably) written as:
static void Replace (Bitmap b) { // Do some work with b }
As it is, the second version may well be more expensive than the first, depending on exactly what the method does. Parameters should only be passed by reference when they actually need to be - when the value of the parameter is changed (which it isn't in this case, even though the object it refers to may be modified).
> > new ArrayList().Add("Hello"); > > [quoted text clipped - 6 lines] > arraylist, although object is still alive and kicking in memory, but it > will be collected during next GC. Yes - but only *after* the Add method has finished. That's the important thing in the example.
> Together with all string objects inside the arraylist. Right? Actually, the string object (there'd only be one, with lots of references) wouldn't be eligible for garbage collection, as interned strings aren't garbage collected until the AppDomain they live in is unloaded.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|