[SDL/C++] Garbage Collection

I once wrote a class whose members lied in sub-fields of “this” cast
as an address-sized union. This way I could create 2^32 instances of
the class without allocating any memory. This only worked because the
instances are all immutable and only existed as a programming
abstraction using CPP macros. (Why not just use macros and leave C++
classes out of it? I wanted the member methods to be compiled once,
and I wanted my program to actually enter those methods, I did not
want them inlined… not all of them anyhow!)On Tue, Jan 27, 2009 at 5:19 PM, Pierre Phaneuf wrote:

It is possible to put that reference in a new
object, but it would be bad form (just like you can make C++
references be NULL, but it’s reasonable to say “hey, don’t do that,
it’s evil!”).


http://codebad.com/

It is possible to put that reference in a new
object, but it would be bad form (just like you can make C++
references be NULL, but it’s reasonable to say “hey, don’t do that,
it’s evil!”).

I once wrote a class whose members lied in sub-fields of “this” cast
as an address-sized union. This way I could create 2^32 instances of
the class without allocating any memory. This only worked because the
instances are all immutable and only existed as a programming
abstraction using CPP macros. (Why not just use macros and leave C++
classes out of it? I wanted the member methods to be compiled once,
and I wanted my program to actually enter those methods, I did not
want them inlined… not all of them anyhow!)

Perfect example.

Don’t do that, it’s evil! :-)On Tue, Jan 27, 2009 at 11:23 PM, Donny Viszneki <donny.viszneki at gmail.com> wrote:


http://pphaneuf.livejournal.com/

And what is worse, very compiler specific.On Wed, Jan 28, 2009 at 6:39 AM, Pierre Phaneuf wrote:

On Tue, Jan 27, 2009 at 11:23 PM, Donny Viszneki <donny.viszneki at gmail.com> wrote:

It is possible to put that reference in a new
object, but it would be bad form (just like you can make C++
references be NULL, but it’s reasonable to say “hey, don’t do that,
it’s evil!”).

I once wrote a class whose members lied in sub-fields of “this” cast
as an address-sized union. This way I could create 2^32 instances of
the class without allocating any memory. This only worked because the
instances are all immutable and only existed as a programming
abstraction using CPP macros. (Why not just use macros and leave C++
classes out of it? I wanted the member methods to be compiled once,
and I wanted my program to actually enter those methods, I did not
want them inlined… not all of them anyhow!)

Perfect example.

Don’t do that, it’s evil! :slight_smile:


http://pphaneuf.livejournal.com/


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

First, a garbage collector has to guess what is the memory structure of your program (if I may put it this way). So, it is not optimal, and the only person who is supposed to know the best how memory is managed is you, the coder.
So why relying on a third party component ? Because people become lazy I think :slight_smile: To link with those old hardwares we were talking about, developers were able to produce amazingly robust softwares in pure assembler. I know, it’s not really comparable with our modern applications involving a lot of heterogeneous components, I admit.
It is just to emphasize the fact that GC can be helpful in some cases, but is just another tool having a particular context of use (just like pointers !)
This context of use can be educational for instance, trying to learn algorithmic to some people without discouraging them with memory considerations. Others may list a lot of possible context of uses of a GC, I’m not to list them.

A memory management technic that has not been mentioned (except if I read the emails too fast, maybe I did), is memory pools. A memory pool keeps track of every allocated memory areas in a centralized manner. You may attach a specific destructor function to each memory area, so that everything gets clear at once at some point of the execution (mostly at the end).
The advantage of that is that a memory pool avoids memory leaks, and in a game, it ensures that there is no in-game memory free (which may cause lags if during action).

Smart pointers or Shared pointers can have 2 policies: either there is a “owner” of a memory area, either the memory area is reference counted (There may be other strategies, I’m interested in knowing them if any). Just like GC, those tools have a specific context of use, it is not a machine for preparing coffee, and developers must make the effort to understand how they work, just like you have to understand how a screwdriver works.

My conclusion is, many situations, many memory management solutions. In any case, you have to understand the limitations and the underlying mechanism. Software development is like clock-making, it is not magic.

Julien

— En date de?: Mer 28.1.09, Paulo Pinto a ?crit?:de: Paulo Pinto
Objet: Re: [SDL] [SDL/C++] Garbage Collection
?: “A list for developers using the SDL library. (includes SDL-announce)”
Date: Mercredi 28 Janvier 2009, 9h05

And what is worse, very compiler specific.

On Wed, Jan 28, 2009 at 6:39 AM, Pierre Phaneuf wrote:

On Tue, Jan 27, 2009 at 11:23 PM, Donny Viszneki <donny.viszneki at gmail.com> wrote:

It is possible to put that reference in a new

object, but it would be bad form (just like you can make C++

references be NULL, but it’s reasonable to say "hey, don’t do that,

it’s evil!").

I once wrote a class whose members lied in sub-fields of “this” cast

as an address-sized union. This way I could create 2^32 instances of

the class without allocating any memory. This only worked because the

instances are all immutable and only existed as a programming

abstraction using CPP macros. (Why not just use macros and leave C++

classes out of it? I wanted the member methods to be compiled once,

and I wanted my program to actually enter those methods, I did not

want them inlined… not all of them anyhow!)

Perfect example.

Don’t do that, it’s evil! :slight_smile:

http://pphaneuf.livejournal.com/


SDL mailing list

SDL at lists.libsdl.org

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Hi,

I hear a lot of developers saying that they manage memory better than any
GC. That might be true, but not on many real life situations.

First many last generation GC systems are able to allocate memory faster
than any standard C/C++ memory allocator that comes with
your compiler of choice. If you use a highly customized memory allocator
that is another matter.

Second it is very easy to misuse memory pools, if you don’t plan correctly
their usage pattern.

Programming with GC enabled language is different than a non GC one, if you
use the same patterns you end up stressing the GC and blaming
the GC for your actions.

And note that many research OS have been done, where the GC is already
builtin, they don’t support any direct memory managment besides the
device driver level.

For example, on the IT area where I work, telecomunications, languages with
manual memory management are now a realm of legacy applications,
or targeting hardware with memory constraints like embed systems with
microcontrolers.

But I agree with Julien, you have to know your problem at hand, weight the
plus and minus for each solution and take the best fit.–
Paulo

On Wed, Jan 28, 2009 at 10:17 AM, julien CLEMENT wrote:

First, a garbage collector has to guess what is the memory structure of
your program (if I may put it this way). So, it is not optimal, and the only
person who is supposed to know the best how memory is managed is you, the
coder.
So why relying on a third party component ? Because people become lazy I
think :slight_smile: To link with those old hardwares we were talking about, developers
were able to produce amazingly robust softwares in pure assembler. I know,
it’s not really comparable with our modern applications involving a lot of
heterogeneous components, I admit.
It is just to emphasize the fact that GC can be helpful in some cases, but
is just another tool having a particular context of use (just like
pointers !)
This context of use can be educational for instance, trying to learn
algorithmic to some people without discouraging them with memory
considerations. Others may list a lot of possible context of uses of a GC,
I’m not to list them.

A memory management technic that has not been mentioned (except if I read
the emails too fast, maybe I did), is memory pools. A memory pool keeps
track of every allocated memory areas in a centralized manner. You may
attach a specific destructor function to each memory area, so that
everything gets clear at once at some point of the execution (mostly at the
end).
The advantage of that is that a memory pool avoids memory leaks, and in a
game, it ensures that there is no in-game memory free (which may cause lags
if during action).

Smart pointers or Shared pointers can have 2 policies: either there is a
"owner" of a memory area, either the memory area is reference counted (There
may be other strategies, I’m interested in knowing them if any). Just like
GC, those tools have a specific context of use, it is not a machine for
preparing coffee, and developers must make the effort to understand how
they work, just like you have to understand how a screwdriver works.

My conclusion is, many situations, many memory management solutions. In any
case, you have to understand the limitations and the underlying mechanism.
Software development is like clock-making, it is not magic.

Julien

— En date de : Mer 28.1.09, Paulo Pinto <@Paulo_Pinto> a
?crit :

De: Paulo Pinto <@Paulo_Pinto>
Objet: Re: [SDL] [SDL/C++] Garbage Collection
?: “A list for developers using the SDL library. (includes SDL-announce)” <
sdl at lists.libsdl.org>
Date: Mercredi 28 Janvier 2009, 9h05

And what is worse, very compiler specific.

On Wed, Jan 28, 2009 at 6:39 AM, Pierre Phaneuf wrote:

On Tue, Jan 27, 2009 at 11:23 PM, Donny Viszneki <donny.viszneki at gmail.com> wrote:

It is possible to put that reference in a new
object, but it would be bad form (just like you can make C++
references be NULL, but it’s reasonable to say “hey, don’t do that,
it’s evil!”).

I once wrote a class whose members lied in sub-fields of “this” cast
as an address-sized union. This way I could create 2^32 instances of
the class without allocating any memory. This only worked because the
instances are all immutable and only existed as a programming
abstraction using CPP macros. (Why not just use macros and leave C++
classes out of it? I wanted the member methods to be compiled once,
and I wanted my program to actually enter those methods, I did not
want them inlined… not all of them anyhow!)

Perfect example.

Don’t do that, it’s evil! :slight_smile:


http://pphaneuf.livejournal.com/


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

A memory management technic that has not been mentioned (except if I read
the emails too fast, maybe I did), is memory pools. A memory pool keeps
track of every allocated memory areas in a centralized manner. You may
attach a specific destructor function to each memory area, so that
everything gets clear at once at some point of the execution (mostly at the
end).
The advantage of that is that a memory pool avoids memory leaks, and in a
game, it ensures that there is no in-game memory free (which may cause lags
if during action).

True, I didn’t think to mention, but I often use a vector<const
shared_ptr > (don’t worry, I also use a typedef for that!)
that I push stuff to when I’m done. Funnily enough, I’ve never had to
do it in a game, because users are so slow, and hitting the heap never
showed up in my profiling (my games are pretty mild, though, they’re
not crazy 3D FPSes!), only in things like network servers (2000
requests per second and up, things get hot!). If you use callbacks,
you can have one in the scope that calls the callback (Cocoa-style),
or you can have a slightly bigger one and clear it right after calling
SDL_UpdateRects.

Reference counting tends to have a cost that automatic GC avoids, due
to having more writes while updating the refcounts. I see this problem
rarely, but in some situations, if all your objects are refcounted
(Firefox is an example of that, eurgh!), it can get hot.

Smart pointers or Shared pointers can have 2 policies: either there is a
"owner" of a memory area, either the memory area is reference counted (There
may be other strategies, I’m interested in knowing them if any). Just like
GC, those tools have a specific context of use, it is not a machine for
preparing coffee, and developers must make the effort to understand how
they work, just like you have to understand how a screwdriver works.

Hehe, machine for preparing coffee, I know a Frenchman when I see one
("?a fait le caf?", eh?). :slight_smile:

There’s some other policies, some good, some less so. auto_ptr is a
transferable single ownership, but proved to be much too dangerous
(non-const right hand side of an assignment? that’s insane! or at
the very least, quite surprising!). weak_ptr has the non-owning
policy, making it safe (when the object it points at is destroyed, it
becomes NULL, sort of).

You are quite correct about having to make the effort to understand
what is going on. I’ve seen so many cases of someone hearing about
smart pointers, changing all his pointers to shared_ptr (like a
robot), experiencing circular references, then declaring smart
pointers to be bad.On Wed, Jan 28, 2009 at 4:17 AM, julien CLEMENT wrote:


http://pphaneuf.livejournal.com/

First many last generation GC systems are able to allocate memory faster
than any standard C/C++ memory allocator that comes with
your compiler of choice. If you use a highly customized memory allocator
that is another matter.

That’s correct, and something like a copying generational garbage
collector can actually increase the speed of an application (outside
of the allocation/deallocation process), by improving the data
locality!

I remember seeing a paper that proved that modern GCs can be as fast
or faster than manual memory management, but indicated that automatic
GC generally needed approximately 5 times the amount of memory to do
the same work. If you can’t afford that memory overhead (think of
Firefox, and multiply it’s memory usage by FIVE, yow!)…

That makes me think… Are they using .NET much more in Vista than XP? ;-)On Wed, Jan 28, 2009 at 5:36 AM, Paulo Pinto wrote:


http://pphaneuf.livejournal.com/

First many last generation GC systems are able to allocate memory
faster
than any standard C/C++ memory allocator that comes with
your compiler of choice. If you use a highly customized memory
allocator
that is another matter.

That’s correct, and something like a copying generational garbage
collector can actually increase the speed of an application (outside
of the allocation/deallocation process), by improving the data
locality!

I remember seeing a paper that proved that modern GCs can be as fast
or faster than manual memory management, but indicated that automatic
GC generally needed approximately 5 times the amount of memory to do
the same work. If you can’t afford that memory overhead (think of
Firefox, and multiply it’s memory usage by FIVE, yow!)…

Doesn’t Firefox has also it’s own type of GC? I thought that is one of
the new features of the 3.* version and the reason why it takes so
much memory (depending on what you think of “much”; I would say around
200MB is much for 10 open tabs). But on the other side it also stays
pretty much stable in memory usage also after some weeks of runtime.

That makes me think… Are they using .NET much more in Vista than
XP? :wink:

“They” is MS or Firefox? Doesn’t has Vista .NET integrated and some of
its components uses it?

(And I hope Firefox will never use/require .NET.)Am 28.01.2009 um 20:42 schrieb Pierre Phaneuf:

On Wed, Jan 28, 2009 at 5:36 AM, Paulo Pinto wrote:

First many last generation GC systems are able to allocate memory faster
than any standard C/C++ memory allocator that comes with
your compiler of choice. If you use a highly customized memory allocator
that is another matter.
Yeah, but the performance problems of GC aren’t about allocation in the first
place; they’re about deallocation.

That’s correct, and something like a copying generational garbage
collector can actually increase the speed of an application (outside
of the allocation/deallocation process), by improving the data
locality!
Yeah, locality of reference is great. Really helps out by keeping as much
data as possible in the CPU cache. But what does that have to do with
garbage collection? I don’t see the correlation. That sounds a whole lot
like the way FastMM4, the default memory manager, for Delphi, handles
things. (Check the Implementation Details section at
http://dn.codegear.com/article/33416 ) Or am I just missing something?>----- Original Message ----
From: Pierre Phaneuf
Subject: Re: [SDL] [SDL/C++] Garbage Collection

Yes, Pierre, I’m trying to bring the french attitude to SDL :wink:
By the way, I’m a software engineer on the Gocad project, school of geology, in Nancy. Sorry to the others for this little spam ^^

Julien

— En date de?: Mer 28.1.09, Pierre Phaneuf a ?crit?:> De: Pierre Phaneuf

Objet: Re: [SDL] [SDL/C++] Garbage Collection
?: “A list for developers using the SDL library. (includes SDL-announce)”
Date: Mercredi 28 Janvier 2009, 20h42
On Wed, Jan 28, 2009 at 5:36 AM, Paulo Pinto wrote:

First many last generation GC systems are able to
allocate memory faster
than any standard C/C++ memory allocator that comes
with
your compiler of choice. If you use a highly
customized memory allocator
that is another matter.

That’s correct, and something like a copying
generational garbage
collector can actually increase the speed of an
application (outside
of the allocation/deallocation process), by improving the
data
locality!

I remember seeing a paper that proved that modern GCs can
be as fast
or faster than manual memory management, but indicated that
automatic
GC generally needed approximately 5 times the amount of
memory to do
the same work. If you can’t afford that memory overhead
(think of
Firefox, and multiply it’s memory usage by FIVE,
yow!)…

That makes me think… Are they using .NET much more in
Vista than XP? :wink:


http://pphaneuf.livejournal.com/


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Thanks for the article. Pascal will always have a place on my heart :slight_smile:

The JVM GC is very customizable and you can tune it a lot
http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

And tools like Visual VM also help a lot
https://visualvm.dev.java.net/features.html

.Net has similar tools and customization processes. The same goes for other
GC
enabled languages.

One has to learn how to work in GC enabled languages, if you allocate memory
like
crazy, the GC might have to do lots of work and even stop the world, which
you don’t
want to have. Another type of pattern should be used.

The same way a programmer learns that a OOP language has a different
approach than
a structured one, the same applies to when one learns how to program in GC
enabled languages.

But even modern C++ is GC enabled if you want to. If one uses STL for data
structures and
boost pointers, you only need to touch raw memory management in special
cases. And even though
GC support was left out of C++0x, it might come on the next revision
whenever it might be.

In a few years/decades raw memory management might be left to the realm of
device drivers.

Oberon, SPIN, Singularity, House are all examples of OS where the GC is part
of the system.

Sure there will always be cases where manually managing memory will make
sense, as it still
does to code in ASM nowdays for specific cases. I for one won’t like to be
on a airplane where
the computer decides to do a global collection in mid flight.–
Paulo

On Wed, Jan 28, 2009 at 10:41 PM, Mason Wheeler wrote:

----- Original Message ----

From: Pierre Phaneuf
Subject: Re: [SDL] [SDL/C++] Garbage Collection

First many last generation GC systems are able to allocate memory faster
than any standard C/C++ memory allocator that comes with
your compiler of choice. If you use a highly customized memory allocator
that is another matter.
Yeah, but the performance problems of GC aren’t about allocation in the
first
place; they’re about deallocation.

That’s correct, and something like a copying generational garbage
collector can actually increase the speed of an application (outside
of the allocation/deallocation process), by improving the data
locality!
Yeah, locality of reference is great. Really helps out by keeping as much
data as possible in the CPU cache. But what does that have to do with
garbage collection? I don’t see the correlation. That sounds a whole lot
like the way FastMM4, the default memory manager, for Delphi, handles
things. (Check the Implementation Details section at
http://dn.codegear.com/article/33416 ) Or am I just missing something?


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

That’s correct, and something like a copying generational garbage
collector can actually increase the speed of an application (outside
of the allocation/deallocation process), by improving the data
locality!

Yeah, locality of reference is great. Really helps out by keeping as much
data as possible in the CPU cache. But what does that have to do with
garbage collection? I don’t see the correlation. That sounds a whole lot
like the way FastMM4, the default memory manager, for Delphi, handles
things. (Check the Implementation Details section at
http://dn.codegear.com/article/33416 ) Or am I just missing something?

Note the bits about “copying” and “generational” (see


for some info). A copying GC, well, copies the objects still in use,
so that puts them all together, improving the spatial locality. This
can get expensive, but together with a generational strategy (which
has a pool for every run of the garbage collector, and garbage
collects objects less and less often the longer they have “survived”),
it actually does an excellent job of keeping related things together,
and not spending all its time copying stuff around. See this paper for
example: http://portal.acm.org/citation.cfm?id=1133964On Wed, Jan 28, 2009 at 4:41 PM, Mason Wheeler wrote:


http://pphaneuf.livejournal.com/