[.net] Forgive my ignorance but shouldn't it implemented a reference counter?

Started by
19 comments, last by Talonius 18 years, 1 month ago
I was trying C sharp and after falling in love with its features (like how easy using SDL.net became) I am having some problems memory management aside. There is a garbage collector which means that it will wait till you are using a lot of memory and then run a long process looking for objects that can be destroyed. Let me be worried about efficiency because of that, but well I thought that if I could make sure to release references to objects I won't use I could keep the memory usage low so the garbage collector would be seldom executed or maybe when a level ends or when a level is loaded - moments where the garbage collector wouldn't be considered. The problem is that I can't really make endure to let it destroy objects objects I won't use again. But well the point of this thread is to ask about the behaviour of this code:

using System;

namespace destructortest
{
	class Employee: System.Object [IDisposable]
	{
		
	    string m_name;
	
	    public Employee(string name)
	    {
	        m_name = name;
	    }
	
	    ~Employee()
	    {
	        Console.WriteLine("Employee destructor executed.");
	    }
	}
	
	class MainClass
	{
		public static void Main(string[] args)
		{
			Employee e=new Employee("whatever");
			Console.WriteLine("C");
			set e=null;
			Console.WriteLine("B");		
			Console.ReadLine();
		}
	}
}


the Employee Object created there is only pointed by the e variable and I eventually set e to null. According to my logic the framework should note that there is nothing pointing to that employee and free the memory . But it doesn't, the object is destroyed once the program ends. It could be that programmers may not like the object to be destroyed there immediatelly, still I doubt they would preffer that object to be destroyed along with 1000 other objects by the garbage collector. I thought that there could be a way to ask the garbage collector to clean an object if possible, but well it seems that it is only possible to make the garbage collector collect all the memory used and the only option is to let you choose the generation of the object. So I would like an explanation for this behaviour or a suggestion for alternatives. And yes, I am a C++ junkie.
------ XYE - A new edition of the classic Kye
Advertisement
There is a special pattern to ensure disposal of single objects: dispose pattern

In general you should avoid dispose routines as they have the most unusable semantics you can imagine. Debug output might be ok, RAII for ressources external to .NET is ok too, anything more is asking for trouble.
if you really want that sort of destructors, then you shouldnt use .net.
use unmanaged c++ or something.

the whole idea of a garbage collector is, that you dont have to care about freeing memory. the garbage collector does it for you.
you can use GC.Collect() to force a garbage collection, but this will hurt performance.
dispose would only help me to dispose disposable elements used by the object and unmanaged stuff.

I don't think it would work for the memory took by 'normal' attributes.


Edit: Seems I was wrong let me check more into it.

Cody: I do not think garbage collecting should be considered the main feature of .net I actually preffer C# for the API, the syntax and mainly .net assemblies, using DLL is no longer a pain in the ass.

And I would trust GC for some objects what I want to avoid is to let it become full of objects that are easy to get rid of.
------ XYE - A new edition of the classic Kye
There is a simple reason why stuff isn't collected instantly: It's too expensive to do that.

Automatic memory management always comes with a price, in reference counted languages it's memory overhead for the counter and runtime overhead for updating the counter. In GC-languages the price is that you waste some memory with dead objects.
Why do you care if your application hasn't freed up the memory at a particular point? The idea of garbage collection is that you don't have to worry about freeing things, and when your memory usage becomes too high you are cleaned up after.

Quote:I think that if you set to null .net should not that there isn't anything pointing to that object and get rid of it

It is not so simple:
Object o1 = (something);Object o2 = o1;o1 = null;


Quote:I guess .net ... has no future in games

I don't see why not having direct control over memory makes it unusable for games.
seems I took too much time to remove that line so I 'll have to deal with it.

Under the theory that you were forced into filling your memory up and then the garbage collector will be executed leads to 2 things:

* memory is increasing up with no reason and constantly
* Garbage collector will be executed when you don't want it to be executed, like in the middle of your game and cause a freeze if you are using a lot of memory.

Just saying that If you could manage a little of memory you will be able to improve performance. And a way to improve performance would be removing an object once there is no variable referencing to it automatically. Just a theory.

But now that I saw the dispose pattern I guess I might check more about it.

---

Quote:Object o1 = (something);
Object o2 = o1;
o1 = null;


A simple reference counter.

o1 = new whatever.

The (new whatever) has reference counter increased (1)
o2 = o1 the object pointed by o1 gets reference counter increased (2)
o1 = null the object pointed by o1 gets reference counter decreased (1)

so 1 is not 0 and it would not clean anything

until you set o2 to null.

And it is just a simple thing, for most complex things like circular references (where just counting wouldn't note anything) it won't do anything and you will have to rely on the GC.

The question was: Why the lack of an "auto destroy object when nothing is referencing to it" system?
------ XYE - A new edition of the classic Kye
the Garbage colector doesn't run when a variable runs out ou scope, or when is set to null it runs when a certain amount of memory (1Mb curenty) has been alocated (Runs level 0 colection which means it only walks the stack and heap starting from top level stack frames to see wich references have been nulled out) so if you want a see a garbage colection happen try alocatin more than 1 MB of memory.

Second the GC doesn't run on the same thread with the code that alocates the objects so the destruction of objects takes place without interupting the program flow. (for GC collection lev 0 and 1)

But the GC can pause the main thread when a memory compacting operation occurs because it needs to reset the references to the new memory locacations after compacting. So if you're going to have the memory compacted it means that you reached the limit wich means also the swap file comes into play so the big performance penalty here comes from swaping and not from memory compacting or gc collections
Well then I guess 1MB is not too much. And it executes in another thread, it shouldn't be much problem I guess.

But what if you actually have a lot of objects that are still being used and take a lot of memory? wouldn't it cause the GC to execute periodically without any success?

Side note: I noted some classes in the API are actually disposable, that's something you don't hear about so often, so you might actually have to control some memory usage anyways.
------ XYE - A new edition of the classic Kye
Quote:Original post by Vexorian
But what if you actually have a lot of objects that are still being used and take a lot of memory? wouldn't it cause the GC to execute periodically without any success?


Actualy the CLR is optimized for lots of small obect allocations with short lifespan, and is also otimized not to take GC perf hits based on the number of objects present in memory. To put it another way if you have a milion objects alocated and you alocate 1 thousant more the perf is the same almost as having no object alocated and alocating a thousant. This is accomplished using object generations. So objects that live through one garbage colection are ugraded to level 1 obects, wich means they wont' be walked or counted when generation 0 collections occur.

Anyway it's better not to have to many allocations in the middle of the progragam runing but rather at initialization time. No alocations also means no GC's will ocur so all the proc cycles are for your use only ;-)

Quote:Original post by Vexorian
Side note: I noted some classes in the API are actually disposable, that's something you don't hear about so often, so you might actually have to control some memory usage anyways.


the Disposabe pattern is in DotNET for releasing resources (files, handles, unmanaged memory, etc) not memory. You can't release managed memory using disposable object but you can release resources in a deterministic way as oposed to gc finalization (non dedetrministic : time and order of finalisations can't be determined acurately)

This topic is closed to new replies.

Advertisement