D on next-gen consoles and for game development

H. S. Teoh hsteoh at quickfur.ath.cx
Fri May 24 12:05:14 PDT 2013


On Fri, May 24, 2013 at 07:55:44PM +0200, deadalnix wrote:
> On Friday, 24 May 2013 at 15:17:00 UTC, Manu wrote:
> >Errr, well, 1ms is about 7% of the frame, that's quite a long time.
> >I'd be feeling pretty uneasy about any library that claimed to want
> >7% of the whole game time, and didn't offer any visual/gameplay
> >benefits...  Maybe if the GC happened to render some sweet water
> >effects, or perform some awesome cloth physics or something while it
> >was at it ;) I'd say 7% is too much for many developers.

OK.


> >I think 2% sacrifice for simplifying memory management would probably
> >get through without much argument.  That's ~300µs... a few hundred
> >microseconds seems reasonable.  Maybe a little more if targeting
> >30fps.  If it stuck to that strictly, I'd possibly even grant it
> >permission to stop the world...

Makes sense. So basically some kind of incremental algorithm is in
order.


> That is kind of biased, as you'll generally win on other aspects.
> You don't free anymore, you don't need to count reference (which can
> become qui te costly in multithreaded code), etc . . .
> 
> Generally, I think what is needed for games is a concurrent GC. This
> incurs a memory usage overhead (floating garbage), and a tax on
> pointers write, but eliminate pause.
> 
> That is a easy way to export a part of the load in another thread,
> improving concurrency in the application with little effort.

Wouldn't that require compiler support? Unless you're willing to forego
nice slicing syntax and use custom types for all references / pointers.


> With real time constraint, a memory overhead is better than a pause.
> 
> >One important detail to consider for realtime usage, is that it's
> >very unconventional to allocate at runtime at all...  Perhaps a
> >couple of short lived temp buffers each frame, and the occasional
> >change in resources as you progress through a world (which are
> >probably not allocated in GC memory anyway).  Surely the relatively
> >high temporal consistency of the heap across cycles can be leveraged
> >here somehow to help?
> 
> That is good because it means not a lot of floating garbage.

Isn't the usual solution here to use a memory pool that gets deallocated
in one shot at the end of the cycle? So during a frame, you'd create a
pool, allocate all short-lived objects on it, and at the end free the
entire pool in one shot (which could just be a no-op if you recycle the
pool memory for the temp objects in the next frame). Long-lived objects,
of course, will have to live in the heap, and since they usually aren't
in GC memory anyway, it wouldn't matter.

A naïve, hackish implementation might be a function to reset all GC
memory to a clean slate. So basically, you treat the entire GC memory as
your pool, and you allocate at will during a single frame; then at the
end of the frame, you reset the GC, which is equivalent to collecting
every object from GC memory except it can probably be done much faster
than a real collection cycle. Anything that needs to live past a single
frame will have to be allocated via malloc/free. So this way, you don't
need any collection cycle at all.

Of course, this may interact badly with certain language constructs: if
any reference to GC objects lingers past a frame, you may break language
guarantees (e.g. immutable array gets reused, violating immutability
when you dereference the stale array pointer in the next frame). But if
the per-frame code has no escaping GC references, this problem won't
occur. Maybe if the per-frame code is marked pure? It doesn't work if
you need to malloc/free, though (as those are inherently impure -- the
pointers need to survive past the current frame). Can UDAs be used
somehow to enforce no escaping GC references but allow non-GC references
to persist past the frame?


T

-- 
People say I'm indecisive, but I'm not sure about that. -- YHL, CONLANG


More information about the Digitalmars-d mailing list