Re: C++ sucks for games
From: Alex Drummond (a.drummond_at_ucl.ac.uk)
Date: 10/31/04
- Next message: Rahul Jain: "Re: C++ sucks for games"
- Previous message: Alex Drummond: "Re: C++ sucks for games"
- In reply to: Mark A. Gibbs: "Re: C++ sucks for games"
- Next in thread: jayessay: "Re: C++ sucks for games"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Sun, 31 Oct 2004 04:14:15 +0000
> read the fine print: "allocating a large pool at the start of each
> board/level/or more recently area". that implies also that i would
> deallocate all level data at the end of a level, so all expensive
> operations are between levels. in other words, i may have implemented my
> own garbage collector, but i've done it better than lisp could have.
Whether or not it's better than what Lisp could have done is an empirical
question, and I don't see any empirical evidence here. Presumably if you
have a reference to some level data, and you make that reference go out of
scope at the end of a level, you'd achieve pretty much the same effect. And
if you are keeping data in memory which is no longer referenced, I really
doubt that this waste of memory will improve performance.
> furthermore, i don't *need* to have smart pointers - the memory is
> automatically cleaned up, remember? for those objects which will be hit
> the hardest by being counted - those that hang around the longest or are
> used the most - i would probably choose not to, if i found it too
> wasteful.
Well OK, you don't need smart pointers because your using an example of a
trivial memory management problem. I.e. load a level, play a level, unload
a level. A GC doesn't need smart pointers to do this either.
> garbage collectors are neat toys, and they do have their uses sometimes,
> but though the average programmer may be dumb as toast, they're still
> smarter than any garbage collector.
I guess the average programmer is also smarter than the part of a C++
compiler which handles lexical variable scoping. Does this mean that
programmers should handle their own variable scoping discipline? This would
allow many useful techniques, such as sharing local variables between
functions which did not call themselves recursively.
> fair enough, except that you can know exactly when those deallocations
> will occur in the non-gc environment, and you can postpone them if you
> really can't afford the time in the current block. in my opinion, that
> negates the advantage.
You can easily postpone a GC by turning it off while some block of code
executes.
> beats the hell out of me - i don't program garbage collectors, and i'm
> not really inclined to argue the benefits of one implementation vs.
> another.
Presumably because you don't know what you're talking about when it comes to
the implementation of GCs. I take it that you accept my point that
reference counting is usually slow compared to more sophisticated methods.
> you and i apparently looked at the same slides and can away with very
> different perceptions. the graph you put up was apparently allocating
> and deallocating lots and lots of small nodes (i estimate 16 bytes)
> repeatedly. because the gc can perform all deallocations en masse and it
> doesn't have to count references i'm not particularly surprised at the
> result.
>
> i can't imagine trying to do that in modern game code. more likely i'd
> use pools, which means these results probably closer approximate
> performance:
> http://www.hpl.hp.com/personal/Hans_Boehm/gc/nonmoving/html/slide_23.html
> (or
> http://www.hpl.hp.com/personal/Hans_Boehm/gc/nonmoving/html/slide_24.html)
>
> and of course, the critical measurement in game performance is the pause
> time. what makes the gc behaviour really bad (besides the obviously
> glaring difference) is that that pause time can theoretically happen
> anywhere, which is hardly ideal.
You're completely mistaken to compare your use of pools with a GC allocating
large objects. A GC is going to allocate large pools of memory at a time,
just as you are doing manaully. You may be allocating large pools, but many
of the objects held in these pools are going to be small (objects
representing entities in the game world, data used by game AI code, etc.)
This is exactly what a GC will do for you, it will optimise memory
management by storing small objects in large pools, and as you say,
"deallocating them en masse". If you actually have some large objects, you
presumably won't be losing references to them every few fractions of a
second (certainly not if they represent some kind of persistent game state)
so the overhead from deallocating them will be negligible. Generally, big
objects tend to stick around longer than small objects, so it's not so bad
if they take up a bit more GC time.
If there are critical bits of code where you just cannot have the overhead
of any GC at all, just turn off the GC for that bit of code.
> maybe you can tune the garbage collector by setting some flags that
> either disable the gc unless you explicitly enable it, or somehow
> amortize that pausing time... but wasn't the gc supposed to eliminate
> being concerned about memory management?
I don't think GC was really supposed to do that. Although it does for the
vast majority of the code in the vast majority of programs.
> my argument from the beginning has been: no language or language feature
> solves everything, so use what's best to solve the problem you're trying
> to solve. i fail to see how these numbers don't support that.
Empirical evidence has no bearing on the truth of a platitude.
> my biggest beef with gc languages is that generally they offer no other
> options besides garbage collection. the reason i choose to use c++ is
> that for any given allocation, i can choose to do it on the stack, via
> manual memory management or smart pointers. whichever works best to suit
> the problem at hand.
>
> so perhaps my resistance to garbage collection is a bit irrational. but
> i believe that a wholesale switch to garbage collection is a case of
> throwing the baby out with the bathwater. it's not hard to demonstrate
> that garbage collection isn't perfect, and *not* using it gives you more
> options, that usually - at least in my field - are better options.
Well, the whole argument has been about whether those other options are
actually better.
Alex
Mark A. Gibbs wrote:
>
> Alex Drummond wrote:
>
>>>i make games, and in the context of games, a gc is kind of a silly idea.
>>>generally speaking, my allocation pattern in games tends along the line
>>>of allocating a large pool at the start of each board/level/or more
>>>recently area, then using smart pointers to lock and unlock sections of
>>>that pool as memory is used, then just freeing the entire pool at the
>>>end.
>>
>>
>> I.e. implemeting your own garbage collector. GCs generally allocate big
>> blocks of memory at the start of program execution and then manage the
>> use of those blocks. Using smart pointers is going to be less efficient
>> than using a GC, because reference counting is quite inefficient.
>
> read the fine print: "allocating a large pool at the start of each
> board/level/or more recently area". that implies also that i would
> deallocate all level data at the end of a level, so all expensive
> operations are between levels. in other words, i may have implemented my
> own garbage collector, but i've done it better than lisp could have.
>
> furthermore, i don't *need* to have smart pointers - the memory is
> automatically cleaned up, remember? for those objects which will be hit
> the hardest by being counted - those that hang around the longest or are
> used the most - i would probably choose not to, if i found it too
> wasteful.
>
> garbage collectors are neat toys, and they do have their uses sometimes,
> but though the average programmer may be dumb as toast, they're still
> smarter than any garbage collector.
>
>>>in fact, the gc would take something away, because non-deterministic
>>>deallocations can fugger things up in exactly the wrong place. i already
>>>evaluated java for game design, and this was one of the major blows
>>>against it - you can't control the gc (portably).
>>
>>
>> The amount of time spent freeing dereferenced pointers is also fairly
>> unpredictable. It's perfectly possible to have a GC with some sort of
>> soft-real time constraint, where it's guaranteed that the GC will not
>> spend lots of time freeing memory before allowing other threads of the
>> program CPU time. This sort of guarantee is pretty much impossible to get
>> with reference counting (unless you really want to look at which
>> references get lost when for every code path), so GC seems to have the
>> advantage here.
>
> fair enough, except that you can know exactly when those deallocations
> will occur in the non-gc environment, and you can postpone them if you
> really can't afford the time in the current block. in my opinion, that
> negates the advantage.
>
>>>stop. i have heard that several times in this discussion. i provided
>>>numbers indicating that garbage collection was over 15 times slower than
>>>smart pointers. i have seen absolutely no evidence to the contrary.
>>
>>
>> 1) Your numbers are pretty suspect for reasons I gave earlier.
>
> i agree, but they're still the only ones.
>
>> 2) If reference counting is so damn efficient, /why don't any cutting
>> edge modern GCs use it?/ If reference counting is a fast as you say it
>> is, a modern GC could use it and get equivalent memory management
>> performance to C++ code using smart pointers; you'd get all the speed of
>> C++ without any
>> of the difficulty. You're simply wrong here I'm afraid. Reference
>> counting
>
> beats the hell out of me - i don't program garbage collectors, and i'm
> not really inclined to argue the benefits of one implementation vs.
> another.
>
>> gives very poor space performance (all those reference count fields to
>> store) and unpredictable, slowish time performance. See for example this
>> short discussion of the merits of reference counting smart pointers
>>
(http://www.hpl.hp.com/personal/Hans_Boehm/gc/nonmoving/html/slide_1.html)
>> including this performance comparison putting a C++ GC ahead of reference
>> counting smart pointers
>>
(http://www.hpl.hp.com/personal/Hans_Boehm/gc/nonmoving/html/slide_11.html).
>> It also includes an analysis of "maximum pause time", which shows that GC
>> has no great disadvantage here either, especially not in multithreaded
>> code, where thread-safe reference counting is extremely expensive.
>
> you and i apparently looked at the same slides and can away with very
> different perceptions. the graph you put up was apparently allocating
> and deallocating lots and lots of small nodes (i estimate 16 bytes)
> repeatedly. because the gc can perform all deallocations en masse and it
> doesn't have to count references i'm not particularly surprised at the
> result.
>
> i can't imagine trying to do that in modern game code. more likely i'd
> use pools, which means these results probably closer approximate
> performance:
> http://www.hpl.hp.com/personal/Hans_Boehm/gc/nonmoving/html/slide_23.html
> (or
> http://www.hpl.hp.com/personal/Hans_Boehm/gc/nonmoving/html/slide_24.html)
>
> and of course, the critical measurement in game performance is the pause
> time. what makes the gc behaviour really bad (besides the obviously
> glaring difference) is that that pause time can theoretically happen
> anywhere, which is hardly ideal.
>
> maybe you can tune the garbage collector by setting some flags that
> either disable the gc unless you explicitly enable it, or somehow
> amortize that pausing time... but wasn't the gc supposed to eliminate
> being concerned about memory management?
>
>> So the numbers don't all come down on your side of the argument, far from
>> it.
>
> my argument from the beginning has been: no language or language feature
> solves everything, so use what's best to solve the problem you're trying
> to solve. i fail to see how these numbers don't support that.
>
> my biggest beef with gc languages is that generally they offer no other
> options besides garbage collection. the reason i choose to use c++ is
> that for any given allocation, i can choose to do it on the stack, via
> manual memory management or smart pointers. whichever works best to suit
> the problem at hand.
>
> so perhaps my resistance to garbage collection is a bit irrational. but
> i believe that a wholesale switch to garbage collection is a case of
> throwing the baby out with the bathwater. it's not hard to demonstrate
> that garbage collection isn't perfect, and *not* using it gives you more
> options, that usually - at least in my field - are better options.
>
> however - to repeat myself yet again - if garbage collection turns out
> to be the best solution for a given problem, i'll use it. whatever works
> best.
>
> indi
- Next message: Rahul Jain: "Re: C++ sucks for games"
- Previous message: Alex Drummond: "Re: C++ sucks for games"
- In reply to: Mark A. Gibbs: "Re: C++ sucks for games"
- Next in thread: jayessay: "Re: C++ sucks for games"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|