Smart pointers instead of GC?

pjmlp pjmlp at progtools.org
Mon Dec 31 06:43:25 PST 2012


On Monday, 31 December 2012 at 14:05:01 UTC, Kiith-Sa wrote:
> I think you're overthinking this way too much.
>
> I'm writing a game engine, where latency is much more important
> than in your case. Even 10ms would translate to visible jitter.
> GC's not an issue, and disabling it permanently is very
> counterproductive _unless_ you've exhausted all other options
> (which you're unlikely to, as you can do everything you can do 
> in
> C++).  All you have to do is care about how you allocate and, if
> GC seems to be an issue, profile to see _where_ the GC is being
> called most and optimize those allocations.
>
> Basic rules:
>
> For classes with one or few instances (singletons, etc.), GC is
> not an issue. For classes with hundreds-thousands of instances,
> it might be an issue. Profile. For classes with more instances,
> it probably is an issue. Profile, reuse instances, use structs,
> manually allocate.  Arrays: To avoid reallocation on append, use
> array.assumeSafeAppend() before the append (Assumes that the
> array is not a slice of a bigger array that would get its data
> overwritten).
>
> If appending a lot, use std.array.Appender. If you need manually
> allocated storage, use std.container.Array, or create a wrapper
> around malloc/free. I'm using a templated wrapper that allows me
> to record how much memory/instances was allocated with which
> types.  Destructors: Structs are RAII like in C. And you can
> easily create a malloc wrapper that will act exactly like
> new/delete in C++.
>
> Classes: call destroy(instance). Calls the dtor, but doesn't
> deallocate the class (GC will do that later). Not much different
> from deleting a class allocated through new in C++ (which is 
> what
> you do most of the time in C++).  If you absolutely need to free
> the memory, create malloc/free wrappers for classes.  In my 
> case,
> classes are used for polymorphic stuff, which are usually single
> or few-instance objects. Structs are used for most of the
> many-instance objects (e.g. components of game entities), and 
> are
> usually stored in manually allocated arrays.
>
> GC is _very_ useful for stuff like closures, which can greatly
> simplify some code. Also, while I maintain that disabling GC
> completely is a bad idea, it might be useful to disable it in a
> small area of code _after_ profiling shows that GC is being
> called too much there.
>
> In my YAML parser library, I've found after profiling that 18% 
> of
> time was spent in GC. Most of that was in a small piece of code
> that repeatedly allocated memory. Disabling GC before this code
> and reenabling it after (scope(exit) to avoid leaking disabled
> GC) resulted in GC taking ~2% of time, because many unnecessary
> collects were consolidated into one after the GC was reenabled.
> Memory usage didn't take a hit, because this was actually a
> fairly small piece of code, not doing too many allocations per
> call, just called very often.

I think it will still take a few generations of programmers until 
everyone is confortable with using GC enabled languages for 
systems programming scenarios.

Most people nowadays are not aware of what has already been done 
in academia, or are burned by bad experiences caused by whatever 
reasons.

This situation will only improve when developers start aproaching 
the same class of problems with open minds on how to solve them 
in new ways.

--
Paulo


More information about the Digitalmars-d mailing list