www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - OSNews thread here degenerates into GC vs not

reply Georg Wrede <georg.wrede nospam.org> writes:
As just seen, much is discussed about the D GC.

It seems to be like the rotary engine: anybody who looks at the 
blueprints says this simply can't work, and it still does. And pretty 
well too, in fact.

Anybody can (and frequently does) conjure up situations where the GC 
"starts smoking", and still, our real-life programs seem to "just work".

Who's had a GC problem /for real/?
Nov 20 2006
next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Georg Wrede wrote:
 As just seen, much is discussed about the D GC.
 
 It seems to be like the rotary engine: anybody who looks at the 
 blueprints says this simply can't work, and it still does. And pretty 
 well too, in fact.

I always look at the schematic for a jet engine, and listen to the explanations for how it works. I never bought the explanations, to me it just looks like it isn't going to work. It looks like the flame will blow forwards just as much as blow backwards, and there will be no net thrust. I finally took a course in college on jet engine cycle analysis, and found out the reason the flame doesn't blow forward is the compressor produces enough pressure to prevent it. That's why in order to start a jet engine, you have to spool up the compressor first with some external power source. A jet engine "compressor stall" happens when not enough air is coming in the inlet to block the flame from coming forwards, and the flame blows forward, stopping the engine.
 
 Anybody can (and frequently does) conjure up situations where the GC 
 "starts smoking", and still, our real-life programs seem to "just work".
 
 Who's had a GC problem /for real/?

Nov 20 2006
parent reply "John Reimer" <terminal.node gmail.com> writes:
On Mon, 20 Nov 2006 15:54:18 -0800, Walter Bright  
<newshound digitalmars.com> wrote:

 Georg Wrede wrote:
 As just seen, much is discussed about the D GC.
  It seems to be like the rotary engine: anybody who looks at the  
 blueprints says this simply can't work, and it still does. And pretty  
 well too, in fact.

I always look at the schematic for a jet engine, and listen to the explanations for how it works. I never bought the explanations, to me it just looks like it isn't going to work. It looks like the flame will blow forwards just as much as blow backwards, and there will be no net thrust. I finally took a course in college on jet engine cycle analysis, and found out the reason the flame doesn't blow forward is the compressor produces enough pressure to prevent it. That's why in order to start a jet engine, you have to spool up the compressor first with some external power source. A jet engine "compressor stall" happens when not enough air is coming in the inlet to block the flame from coming forwards, and the flame blows forward, stopping the engine.

Hmmm... is that what a flame-out is? I was reading up a little about Helicopter turbines. Some similarities here. -JJR
Nov 20 2006
parent Walter Bright <newshound digitalmars.com> writes:
John Reimer wrote:
 Hmmm... is that what a flame-out is?  I was reading up a little about 
 Helicopter turbines. Some similarities here.

A flame-out can be caused by that, but also by the flame literally being blown out the back.
Nov 20 2006
prev sibling parent reply Mike Capp <mike.capp gmail.com> writes:
Georg Wrede wrote:
 Who's had a GC problem /for real/?

Resharper refactoring plugin for Visual Studio; we use it heavily for our C# development. It regularly freezes up for a minute or so at a time. That's the dotNet runtime's GC, granted, but I have a hard time believing that D's would do better. This isn't as simple as a "GC vs not" debate; I don't think anyone (here, at least) would argue that GC is worthless. Rather there are at least three open questions: 1) When and where is GC appropriate? 2) When it is appropriate, how good is D's implementation of it? 3) When it's not appropriate, how well does D support GC-less (and possibly allocation-less) programming?
Nov 20 2006
next sibling parent Kyle Furlong <kylefurlong gmail.com> writes:
Mike Capp wrote:
 Georg Wrede wrote:
 Who's had a GC problem /for real/?

Resharper refactoring plugin for Visual Studio; we use it heavily for our C# development. It regularly freezes up for a minute or so at a time. That's the dotNet runtime's GC, granted, but I have a hard time believing that D's would do better. This isn't as simple as a "GC vs not" debate; I don't think anyone (here, at least) would argue that GC is worthless. Rather there are at least three open questions: 1) When and where is GC appropriate? 2) When it is appropriate, how good is D's implementation of it? 3) When it's not appropriate, how well does D support GC-less (and possibly allocation-less) programming?

1) Most everywhere in general programming 2) Good, and getting better 3) Very well MORE QUESTIONS? :-)
Nov 20 2006
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
Mike Capp wrote:
 Georg Wrede wrote:
 Who's had a GC problem /for real/?

Resharper refactoring plugin for Visual Studio; we use it heavily for our C# development. It regularly freezes up for a minute or so at a time. That's the dotNet runtime's GC, granted, but I have a hard time believing that D's would do better.

That sounds like bad program design rather than bad GC design. Were the app written using conventional allocation it would either be visibly slow or leak like a sieve.
 This isn't as simple as a "GC vs not" debate; I don't think anyone (here, at
 least) would argue that GC is worthless. Rather there are at least three open
 questions:
 
 1) When and where is GC appropriate?

When the memory overhead is affordable (GCs can consume 40% more system memory for the same amount of user memory as traditional allocators). For very large applications, I think a combination approach would be most likely. GCed memory for most of the throw-away data used during processing and malloc/free or mmap for the rest. This is one area where D has an advantage over Java, as it has built-in support for mixed-mode allocation. For comparison, try allocating an array larger than 1 million elements in Java--the implementation I've tried have been unable to do so (though this woulc obviously be addressed by a specialized GC).
 2) When it is appropriate, how good is D's implementation of it?

From an implementation standpoint, I really have few complaints. The code is fairly clean, succinct, and extensible. As far as application-level use is concerned, that's a difficult question to answer for two reasons. First, I think any well-written app simply won't stress a GC in ways that it wasn't meant to be stressed, so some testing almost necessarily has to create unrealistic conditions to test with. Second, I haven't yet ported or written an app in D that has such refined allocator requirements that the nuances of a GCs performance would matter. Perhaps someone who's written a game in D could comment on the obstacles they encountered related to garbage collector performance?
 3) When it's not appropriate, how well does D support GC-less (and possibly
 allocation-less) programming?

Stack allocation of classes could be better, though 'scope' is a decent enough substitute if heap allocation isn't a problem. Other than that, placement new and delete work so long as classes have new/delete statements defined, but it might be nice if these weren't required. I'm half tempted to add these functions to Object simply to avoid this, assuming it's even possible to have virtual new/delete routines. new( size_t size, void* pos ) { return pos; } delete( void* pos ) { } Sean
Nov 20 2006
next sibling parent reply Mike Capp <mike.capp gmail.com> writes:
Sean Kelly wrote:

 That sounds like bad program design rather than
 bad GC design.  Were the app written using
 conventional allocation it would either be visibly
 slow or leak like a sieve.

Probably. And I suspect the codebase we use it on is larger than usual. But then, you could offer the same retort to any reported "for real" GC problem. [snip sensible answers to questions 1 and 2] Re implementation, I think the concerns are that it's non-copying (which leaves doubts over whether a copying implementation would work) and that it's not type-aware (which effectively forces you to use malloc for large POD allocations, beside the false-positive issues).
 Stack allocation of classes could be better,
 though 'scope' is a decent enough substitute
 if heap allocation isn't a problem.

Yes, that's pretty much my impression. Stack allocation for 'scope' classes would be very nice, but not an absolute must have. It looks as if the gubbins required to do this manually could be templated/mixedin as a stopgap. Thanks for the thoughtful response. Mike
Nov 20 2006
parent reply Mike Parker <aldacron71 yahoo.com> writes:
Mike Capp wrote:
 Sean Kelly wrote:
 
 That sounds like bad program design rather than
 bad GC design.  Were the app written using
 conventional allocation it would either be visibly
 slow or leak like a sieve.

Probably. And I suspect the codebase we use it on is larger than usual. But then, you could offer the same retort to any reported "for real" GC problem.

One thing I've learned during my years with Java is that most "GC problems" are really programmer problems. Such issues can be avoided by "coding to the GC." Unfortunately, this is something that too many developers just don't get. Still there are problems that can't be worked around in obvious ways in code. To eliminate those, Sun goes the extra mile via Java's tools to analyze GC behavior and the command line parameters to fine-tune it, even allowing you to select between several different implementations. That will take care of all but the rare border case. I've not worked with C# more than in passing, so I don't know what sort of tools or options are available to tune the GC. It would be great to have such capabilities in D. I haven't used D extensively enough to know what "coding to the GC" means for the current implementations, but developers who do understand it should be able to avoid the lion's share of issues.
Nov 20 2006
parent Pragma <ericanderton yahoo.removeme.com> writes:
Mike Parker wrote:
 I haven't used D extensively enough to know 
 what "coding to the GC" means for the current implementations, but 
 developers who do understand it should be able to avoid the lion's share 
 of issues.

FWIW, the worst I've run into with the D GC was by aggressive use of opCat: uint[] arr; for(uint i=0; i<65535; i++){ arr ~= i; } Code like this was causing a good amount of memory to be allocated, and then subsequently abandoned - a very small fraction of the heap was actually in use. After I had some help with the guys out on #D to try and track this down, we found that the internal array allocator that was the culprit. The "heap bloat" was easily circumvented with a struct that pretends to be an array, and uses a more conservative re-allocation algorithm by way of using a less conservative *pre*-allocation algorithm. It wasn't rocket-science or anything - anyone who understands what CoW means could hardly call it surprising. So in short: In my experience, GC issues in D aren't uncommon, but then "coding to the GC" is pretty easy to do with some very rudimentary analysis. IMO, wise use of smart datatypes, scope() and delete pretty much cover the rest of the places where the GC is too lazy/slow/dumb to do the job. :) -- - EricAnderton at yahoo
Nov 21 2006
prev sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Sean Kelly wrote:
  Second, I haven't yet ported or written an app in D that has such
 refined allocator requirements that the nuances of a GCs performance 
 would matter.  Perhaps someone who's written a game in D could comment 
 on the obstacles they encountered related to garbage collector performance?

Generally for a realtime 3D app you want to avoid creating and destroying things on a per-frame basis as much as possible. If you do lots of alloc/free then performance will suffer. It's a fact of life. That's true for either GC case or explicitly managed memory. So for example when you make a cool particle system effect you don't allocate each particle, animate it, then destroy it. You usually pre-allocate a fixed number of them and just reuse those over and over. A lot of game developers also use custom allocators like dlmalloc because the platform's malloc isn't fast enough. Writing fixed-sized custom pool allocators is also fairly common. But that kind of thing is perfectly do-able in D too. Basically I think the kind of games that would need custom memory management with D are probably the same kinds of games that would need it under C/C++ as well. Poor floating point performance may be a bigger issue for fancy 3D games than GC, when it comes down to it. --bb
Nov 20 2006
parent reply Steve Horne <stephenwantshornenospam100 aol.com> writes:
On Tue, 21 Nov 2006 10:31:10 +0900, Bill Baxter
<dnewsgroup billbaxter.com> wrote:

Basically I think the kind of games that would need custom memory 
management with D are probably the same kinds of games that would need 
it under C/C++ as well.  Poor floating point performance may be a bigger 
issue for fancy 3D games than GC, when it comes down to it.

Is floating point performance in D a problem? I realise that most 3D work would probably use single precision floats, since higher precision would mostly be overkill and slow things down a bit by increasing the needed memory bandwidth for arrays of vectors. And of course D tends does all calculations in extended precision, but that shouldn't be a problem. The FPU takes as long to multiply two single precision floats as it does to multiply two double precision floats, etc etc. The only thing I can think of is failure to exploit SIMD and similar explicitly parallel instruction sets, but I didn't think that 'just happened' by standard in existing compilers (barring possibly the intel one) anyway. In any case, I thought most games (on Windows, at least) exploited SIMD etc more-or-less by accident, by using the matrix and vector operations in DirectX. In fact, there is supposed to be a trend toward offloading all the viewpoint transformations etc onto the graphics card anyway. Of course I'm at the "I've read some books and played with DirectX and some 3D engines" stage with games programming. That is, I know next to nothing beyond the theory and what's obvious to anyone whos done some real time work. I'm just a bit surprised and curious, is all. If anyone asked me if D was good for games, I'd have thought first about COM support (for DirectX) and any possible issues in calling OpenGL, and then I'd have thought about memory and resource management, and then I'd have expressed some slight concern that the DMD optimiser is probably less sophisticated than those in some other compilers, but I'd figure that the cost from this is probably very small - the important optimisations are usually design-level optimisations (algorithms and data structures). As for memory management, I'd have thought GC would be fine in a game, provided that objects are only allocated at key points such as when moving to another level - the same applying to malloc and free. But I would want a way to trigger a full garbage collection - preferably with another thread using fully preallocated memory keeping some level of updates running - once those key points were completed. That is, you don't want a garbage collection cycle to cause delays while you're in the middle of a level, but do you care about GC delays when you're loading the next level? So long as the between-level music and visuals keep running, probably not. So why not keep the GC benefits for these non-realtime jobs? -- Remove 'wants' and 'nospam' from e-mail.
Nov 21 2006
next sibling parent reply Don Clugston <dac nospam.com.au> writes:
Steve Horne wrote:
 On Tue, 21 Nov 2006 10:31:10 +0900, Bill Baxter
 <dnewsgroup billbaxter.com> wrote:
 
 Basically I think the kind of games that would need custom memory 
 management with D are probably the same kinds of games that would need 
 it under C/C++ as well.  Poor floating point performance may be a bigger 
 issue for fancy 3D games than GC, when it comes down to it.

Is floating point performance in D a problem?

It is slow, but the issue is the optimiser in DMD (and also DMC) does very little optimisation of FP code. So at present it's necessary to code inner loops in asm. (Actually, AFAIK, no compilers are very good at optimising x87 code).
Nov 22 2006
parent Mike Capp <mike.capp gmail.com> writes:
Don Clugston wrote:

 Is floating point performance in D a problem?

very little optimisation of FP code. So at present it's necessary to code inner loops in asm.

I don't see why this need be an issue. For the kind of functionality you're talking about it's probably easier to write the math library in C or Fortran and link it in. It's not as if you need D's advanced features to multiply a bunch of floats.
Nov 22 2006
prev sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Steve Horne wrote:
 I'm just a bit surprised and curious, is all. If anyone asked me if D
 was good for games, I'd have thought first about COM support (for
 DirectX) and any possible issues in calling OpenGL, and then I'd have
 thought about memory and resource management, and then I'd have
 expressed some slight concern that the DMD optimiser is probably less
 sophisticated than those in some other compilers, but I'd figure that
 the cost from this is probably very small - the important
 optimisations are usually design-level optimisations (algorithms and
 data structures).

I haven't done any work in 3d games, but what I hear from every single programmer that has is that they will gladly trade some performance for productivity. I was so shocked when I browsed the C++ CIV4 SDK, I always thought these professional programmers had a tight and clear codebase for such large applications, well they don't. But they are on a tight schedule too and it must be a complex ordeal. I image doing something like this in D saves so much time and complexity, that alone might enable developers to implement higher performance applications. For the most annoying problems with performance in the games I play are due to 'bugs' or design-level bottlenecks it seems, and they are usually patched some months after the release - if you're lucky.
Nov 22 2006
next sibling parent Boris Kolar <boris.kolar globera.com> writes:
== Quote from Lutger (lutger.blijdestijn gmail.com)'s article
 I was so shocked when I browsed the C++ CIV4 SDK, I always thought these
 professional programmers had a tight and clear codebase for such large
 applications, well they don't.

If you meant Civilization IV, then I agree: it performs so badly I can't play it on my old computer or laptop. I think they used Python for game scripting, which is sloooowww.
Nov 22 2006
prev sibling next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
Lutger wrote:
 I haven't done any work in 3d games, but what I hear from every single 
 programmer that has is that they will gladly trade some performance for 
 productivity.
 
 I was so shocked when I browsed the C++ CIV4 SDK, I always thought these 
 professional programmers had a tight and clear codebase for such large 
 applications, well they don't.
 But they are on a tight schedule too and it must be a complex ordeal. I 
 image doing something like this in D saves so much time and complexity, 
 that alone might enable developers to implement higher performance 
 applications. For the most annoying problems with performance in the 
 games I play are due to 'bugs' or design-level bottlenecks it seems, and 
 they are usually patched some months after the release - if you're lucky.

With a tight schedule, a good strategy is to not waste time optimizing any one particular thing until you *know* it is a bottleneck. Game developers tend to be pretty ruthless in applying this principle. For the Civ4 SDK, something that will only be used directly by a tiny fraction of Civ4 users, there's just not a lot of bottom line justification for putting resources there, when compared to say fixing a crash bug that 10% of players are likely to encounter. So yeh, that's why folks like the Civ team and the folks behind Eve Online are willing to go with Python. For most things Python is fast enough, and gets the job done much more quickly than C++. For the small fracton of the code where it's not fast enough, you can always re-write those bits in C and call it from Python. --bb
Nov 22 2006
next sibling parent Sean Kelly <sean f4.ca> writes:
Bill Baxter wrote:
 
 So yeh, that's why folks like the Civ team and the folks behind Eve 
 Online are willing to go with Python.  For most things Python is fast 
 enough, and gets the job done much more quickly than C++.  For the small 
 fracton of the code where it's not fast enough, you can always re-write 
 those bits in C and call it from Python.

The Civ4 post mortem was an interesting read. Even the dev team was surprised at what a good choice Python turned out to be. I think they initially had only planned to write a very small portion of the game in Python and instead ended up writing almost the entire thing in Python. Sean
Nov 22 2006
prev sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Bill Baxter wrote:
  > With a tight schedule, a good strategy is to not waste time optimizing
 any one particular thing until you *know* it is a bottleneck.  Game 
 developers tend to be pretty ruthless in applying this principle.  For 
 the Civ4 SDK, something that will only be used directly by a tiny 
 fraction of Civ4 users, there's just not a lot of bottom line 
 justification for putting resources there, when compared to say fixing a 
 crash bug that 10% of players are likely to encounter.
 
 So yeh, that's why folks like the Civ team and the folks behind Eve 
 Online are willing to go with Python.  For most things Python is fast 
 enough, and gets the job done much more quickly than C++.  For the small 
 fracton of the code where it's not fast enough, you can always re-write 
 those bits in C and call it from Python.
 
 --bb

Civilization 4 is structured in roughly 4 layers: 1. core engine build on gamebryo (C++) - closed source 2. core game logic (120K LoC, a C++ DLL) - open source 3. python scripting (game logic, ui, terrain generation, etc.) 4. xml data (static data) The C++ SDK is layer 2, so this affects all users. I don't know where bottlenecks lie here, but I suspect it is in 1 or 2. I'm not sure (nobody is as it hasn't happened yet), but I wouldn't be surprised that if these parts of a large game are written in D performance will go up instead of down, even if the D compiler doesn't optimize as well as a good C++ compiler. For this kind of application I can't believe a little slower floating point calculation will matter as much as ease of high level design and maintenance optimizations.
Nov 22 2006
parent Bill Baxter <wbaxter gmail.com> writes:
Lutger wrote:
 Bill Baxter wrote:
  > With a tight schedule, a good strategy is to not waste time optimizing
 
 any one particular thing until you *know* it is a bottleneck.  Game 
 developers tend to be pretty ruthless in applying this principle.  For 
 the Civ4 SDK, something that will only be used directly by a tiny 
 fraction of Civ4 users, there's just not a lot of bottom line 
 justification for putting resources there, when compared to say fixing 
 a crash bug that 10% of players are likely to encounter.

 So yeh, that's why folks like the Civ team and the folks behind Eve 
 Online are willing to go with Python.  For most things Python is fast 
 enough, and gets the job done much more quickly than C++.  For the 
 small fracton of the code where it's not fast enough, you can always 
 re-write those bits in C and call it from Python.

 --bb

Civilization 4 is structured in roughly 4 layers: 1. core engine build on gamebryo (C++) - closed source 2. core game logic (120K LoC, a C++ DLL) - open source 3. python scripting (game logic, ui, terrain generation, etc.) 4. xml data (static data) The C++ SDK is layer 2, so this affects all users. I don't know where bottlenecks lie here, but I suspect it is in 1 or 2. I'm not sure (nobody is as it hasn't happened yet), but I wouldn't be surprised that if these parts of a large game are written in D performance will go up instead of down, even if the D compiler doesn't optimize as well as a good C++ compiler. For this kind of application I can't believe a little slower floating point calculation will matter as much as ease of high level design and maintenance optimizations.

Just to be clear I don't think floating point performance is going to make a lick of difference in a game like Civ4. It's only going to even have a chance of being a factor in a game that does massive amounts of realistic physics and accurate 3D collision detection. Hmm and 3D character animation -- that's pretty heavy on the fpu too. --bb
Nov 22 2006
prev sibling parent Walter Bright <newshound digitalmars.com> writes:
Lutger wrote:
 But they are on a tight schedule too and it must be a complex ordeal. I 
 image doing something like this in D saves so much time and complexity, 
 that alone might enable developers to implement higher performance 
 applications. For the most annoying problems with performance in the 
 games I play are due to 'bugs' or design-level bottlenecks it seems, and 
 they are usually patched some months after the release - if you're lucky.

That's something I discovered, too. While D's optimizer is not as good as some C++ optimizers, D source code is much more flexible than C++'s. Hence, it is much easier to adjust the algorithm for better speed. And this is why D code is often able to outperform heavily micro-optimized C++.
Nov 22 2006
prev sibling parent Hasan Aljudy <hasan.aljudy gmail.com> writes:
Mike Capp wrote:
 Georg Wrede wrote:
 Who's had a GC problem /for real/?

Resharper refactoring plugin for Visual Studio; we use it heavily for our C# development. It regularly freezes up for a minute or so at a time. That's the dotNet runtime's GC, granted, but I have a hard time believing that D's would do better.

Might it not be something wrong in the plug-in itself? Does it happen with all plugins or only that particular plugin?
 
 This isn't as simple as a "GC vs not" debate; I don't think anyone (here, at
 least) would argue that GC is worthless. Rather there are at least three open
 questions:
 
 1) When and where is GC appropriate?
 
 2) When it is appropriate, how good is D's implementation of it?
 
 3) When it's not appropriate, how well does D support GC-less (and possibly
 allocation-less) programming?

Nov 20 2006