Has anyone tried that X-Box XMA stuff? I think that's what it's called. I'm curious whether it's worth looking into.
X-Box XMA stuff
Miscellaneous Forums/General Discussion/X-Box XMA stuff I think it's called XNA. It won't run on the Mac (for now) so: no.
Moreover, it won't ( currently ) work for anyone who doesn't have a developer account, so the distribution options are extremely limited.
I've tried it, works well enough. It's just a bit of a novelty though really.
Distribution at this time is limited, however from watching videos from Microsoft they intend the current distribution situation to change dramnatically over the next 12 months. A PRO version will be offered and be a serious possiblity for indie developers.
The framework is nice enough, Rare are already developing somethings with it (using c++ though). You will need to (a) spend a lot of time familiarising yourself with the framework and how it works with c# (b) still need excellent content providers in order to produce good looking stuff. The rest - as always is up to you.
I would say it is definately worth a week's worth of looking into, it may be you surprise youreslf. Just now it's no more than a distraction, but I can see a time when it becomes very important to give people like us exposure to XBOX 360. Rare report that the framework contains about 85% of the full developers kits for XBOX360 so that's pretty good for free I reckon.
The starter kits make life easy to enter the dev. circle with it and there are loads of tutorial sites now up and running with demos etc.
IPete2.
The framework is nice enough, Rare are already developing somethings with it (using c++ though). You will need to (a) spend a lot of time familiarising yourself with the framework and how it works with c# (b) still need excellent content providers in order to produce good looking stuff. The rest - as always is up to you.
I would say it is definately worth a week's worth of looking into, it may be you surprise youreslf. Just now it's no more than a distraction, but I can see a time when it becomes very important to give people like us exposure to XBOX 360. Rare report that the framework contains about 85% of the full developers kits for XBOX360 so that's pretty good for free I reckon.
The starter kits make life easy to enter the dev. circle with it and there are loads of tutorial sites now up and running with demos etc.
IPete2.
I've been having a go at XNA for win32, seems pretty good so far.
I agree with Si. Furthermore XNA is good intentions wrapped in poor execution.
Just get a real 3D engine and be done with it.
Just get a real 3D engine and be done with it.
The point of xna is that its free for win32, and lets you port to x360 if you want for $99, no other engine will do that.
@Smilertoo (Or anyone else with an opinion)
Could you give a comparitive opinion of (For example)
C# and xna (free)
C++ and DBSDK (aprox £40)
C# and DBSDK.net (Approx £40)
Bmax and errr MiniB3D or IrrB3D (Approx £40)
Mine.
-----
C++ and DBSDK Seems like a good thing. Acctualy works now. Gets upgrades slower that DBPro, but does get upgrades. (Problem with this, is that it suddenly needs higher specs, but this is so with most TGC products). The SDK arent Objects thou. (This is just something I have a problem with)
BMax and Whatever. I love Bmax. But without a fully supported 3d engine, (And too be Honest, lack of Graphics commands full stop), ... well you know
Could you give a comparitive opinion of (For example)
C# and xna (free)
C++ and DBSDK (aprox £40)
C# and DBSDK.net (Approx £40)
Bmax and errr MiniB3D or IrrB3D (Approx £40)
Mine.
-----
C++ and DBSDK Seems like a good thing. Acctualy works now. Gets upgrades slower that DBPro, but does get upgrades. (Problem with this, is that it suddenly needs higher specs, but this is so with most TGC products). The SDK arent Objects thou. (This is just something I have a problem with)
BMax and Whatever. I love Bmax. But without a fully supported 3d engine, (And too be Honest, lack of Graphics commands full stop), ... well you know
H&K
I have been quite distracted since Christmas 2006 - I was going head long into XNA which I believe is something I will pick up again later in the year. Have you been following Halo's Leadwerks engine which is now available to try with limitations but there are a number of different options for licensing.
Check out possibly the best future of BMax and 3D...
www.leadwerks.com
IPete2.
I have been quite distracted since Christmas 2006 - I was going head long into XNA which I believe is something I will pick up again later in the year. Have you been following Halo's Leadwerks engine which is now available to try with limitations but there are a number of different options for licensing.
Check out possibly the best future of BMax and 3D...
www.leadwerks.com
IPete2.
If you switch to something like C# or C++, remember that DBSDK is not the only easy-to-use engine out there. From what I've seen, there are quite a few open-source 3D engines that completely blow DBSDK out of the water.
I would choose from something more like this:
C# and xna (free)
C++ and Ogre (free)
C# and Axiom (free)
Bmax and Leadwerks engine ($?)
I'm currently using C++ and Ogre, and it's working quite well. It's just a graphics engine, so I have to find physics/audio libraries myself, but that's no problem.
I haven't done much with XNA, but it seems to me more like DirectX than a high-level 3D engine. Personally, I would rather go the whole way and learn DirectX rather than play around in between. However, if you want to make games for XBox 360, XNA is probably the only way to go.
P.S. BTW, does BlitzMax still lack a simple "delete" command? This is the main reason I moved on to C++; BlitzMax's memory management scheme seems all wrong to me. I mean, which would you rather do: "create object ... delete object" or "create object ... set all non-null references to the object to null to initiate garbage collection"? Personally, I like the traditional simple way.
.... oops, sorry - off-topic :)
I would choose from something more like this:
C# and xna (free)
C++ and Ogre (free)
C# and Axiom (free)
Bmax and Leadwerks engine ($?)
I'm currently using C++ and Ogre, and it's working quite well. It's just a graphics engine, so I have to find physics/audio libraries myself, but that's no problem.
I haven't done much with XNA, but it seems to me more like DirectX than a high-level 3D engine. Personally, I would rather go the whole way and learn DirectX rather than play around in between. However, if you want to make games for XBox 360, XNA is probably the only way to go.
P.S. BTW, does BlitzMax still lack a simple "delete" command? This is the main reason I moved on to C++; BlitzMax's memory management scheme seems all wrong to me. I mean, which would you rather do: "create object ... delete object" or "create object ... set all non-null references to the object to null to initiate garbage collection"? Personally, I like the traditional simple way.
.... oops, sorry - off-topic :)
P.S. BTW, does BlitzMax still lack a simple "delete" command? This is the main reason I moved on to C++; BlitzMax's memory management scheme seems all wrong to me. I mean, which would you rather do: "create object ... delete object" or "create object ... set all non-null references to the object to null to initiate garbage collection"? Personally, I like the traditional simple way.
Interestingly enough Ive just read an article about this on MSDN, and the new managed C++ and the other .net versions now work on the BMax model (sort of), that is the code manager (net) looks ahead and decides if the object is to be used again, then it desides to call the the ~ destructor. It actualy went so far as to tell you when to set the object to NULL. (Well specificly it said dont) The point of xna is that its free for win32
No. The point is that XNA is not an engine - it's an API. Nor does it allow you to "port for the XBox". It allows you to share your source code and media with other XBox 360 developers. Not quite the same thing. if you want to make games for XBox 360, XNA is probably the only way to go.
Actually, if you want to make games for XBox 360, getting a publishing deal with Microsoft is the only way to go. Good luck with that. "create object ... set all non-null references to the object to null to initiate garbage collection"
Missing the point completely. You don't set all references to null, you simply remove it from your collection, and wait for it to go out of scope. And yes, I definitely prefer a language that actively prevents rogue pointer bugs. Interestingly enough Ive just read an article about this on MSDN, and the new managed C++ and the other .net versions now work on the BMax model (sort of), that is the code manager (net) looks ahead and decides if the object is to be used again, then it desides to call the the ~ destructor. It actualy went so far as to tell you when to set the object to NULL
Well, just as long as you can still "delete" objects on demand, it's fine with me. But if .net C++ removes the "delete" keyword, then I don't think I'll be using it.
Garbage collection is fine as a add-on to prevent programmer errors (memory leaks), and also has it's use for resource management. But I think that the ability to "delete" objects on demand should always be an option for the programmer.
For example, which do you prefer - this:
resolutionNode.Free() resolutionNode = Null Settings.Resolution = Null 'Let's hope that the node wasn't referenced anywhere else, or it won't get deleted and we'll have a serious bug
Or this:
Delete resultionNode
You don't set all references to null, you simply remove it from your collection
Isn't "removing it from your collection" synonymous with "set all references to it to null"?
and wait for it to go out of scope
That may be just fine for most windows applications, but in real-time programming you need things to happen exactly when and how you want. No "waiting for the garbage collection to kick in".
And yes, I definitely prefer a language that actively prevents rogue pointer bugs.
First of all, bugs will happen in every language. I'm all for bug detection (like memory leak logs), but I do not like it when a language silently "fixes" your bugs - this can lead to extremely unpredictable behavior.
Garbage collection is fine as a add-on to a standard program as a "memory leak band-aid", but it takes a programmer to actually "heal" the wound.
That may be just fine for most windows applications, but in real-time programming you need things to happen exactly when and how you want. No "waiting for the garbage collection to kick in".
Wish I could find the article again, but my impression was that in the new "Managed" C++ when you called delete, it just gave the nod to the GC, which called the Destrutor when it wanted, so although you think you are deleteing the object you are in fact just setting in to NULL. (I get the impression that you are just using clean C++ so it wont matter to you, but if you are using Managed C++ it isnt working in the same way it used to, and is infact working the way you dont like) For example, which do you prefer
This:Settings.Remove(resolutionNode)Incidently the "Lets hope the node wasn't referenced anywhere else" thing is really only dangerous in C++. If you don't know where all your pointers are pointing, you get rogue pointers, and inadvertently accessing a valid, existing object, is much, much less of a bug than inadvertently accessing (never mind executing) random memory.
Isn't "removing it from your collection" synonymous with "set all references to it to null"?
Depends on your perspective really. in real-time programming you need things to happen exactly when and how you want.
No you don't. PC's are ridiculously overpowered - since most programmers don't use multi threading anyway, the garbage collector will be running on a separate CPU, thus giving you a performance boost. to a standard program as a "memory leak band-aid", but it takes a programmer to actually "heal" the wound.
No, but you do need to change your misconceptions in order to use it effectively. PC's are ridiculously overpowered
That's no excuse to use inefficient code.
since most programmers don't use multi threading anyway, the garbage collector will be running on a separate CPU, thus giving you a performance boost.
I never thought about it that way - that is true. Although as soon as you start using multiple threads (as many games now are doing), you lose that boost.
No, but you do need to change your misconceptions in order to use it effectively.
I understand how it's used effectively quite well. It's just that I do not like it (it's an opinion, obviously) - it introduces a lot of complexity in how objects are created/destroyed.
Where you could previously use a simple delete command to initiate a destructor which destroys an object, now you must create your own custom "deleter" functions, which can be very inconsistent between code libraries.
These "deleter" functions also are incomplete, as they simply remove references to the object - if you still have a reference to the object, it will remain in memory. This can cause trouble when you attempt to access this "hanging" object which may be invalid after being dereferenced.
For example, if you did this in a GC language:
tank.Free() tank.Shoot()
It may be just as unpredictable as this:
delete tank tank.Shoot()
But often the GC variation can be twice as difficult to debug, because you can actually step through the tank.Shoot() method, as though everything was just fine. At least in C++ it will tell you that you're trying to access an object that doesn't exist (sure makes sense to me).
These "deleter" functions also are incomplete, as they simply remove references to the object - if you still have a reference to the object, it will remain in memory. This can cause trouble when you attempt to access this "hanging" object which may be invalid after being dereferenced.
And with your preferred method it will be gone from memory and your reference you still have will crash the program instead. I fail to see how that's better. If you can't manage your objects properly, you get problems either way. If you can manage your objects properly, it works either way. The only difference between the two that I can see is the one to which FlameDuck already referred. If you utilize your collections properly, it's slightly less work with a managed GC.
I don't particularly see a huge advantage to the BMax way, but I certainly can't see a downside.
If you can't manage your objects properly, you get problems either way. If you can manage your objects properly, it works either way.
Exactly. The real question is, which method is more productive?
And with your preferred method it will be gone from memory and your reference you still have will crash the program instead. I fail to see how that's better.
Crashing with an error message is always better than silently ignoring a problem which may easily become a debugging nightmare in the future.
If you utilize your collections properly, it's slightly less work with a managed GC.
Strange, since I see the GC method as being a lot more work. I guess it's all comes down to personal preference.
Strange, since I see the GC method as being a lot more work. I guess it's all comes down to personal preference.
How can it be more? If the only place your objects exist is in their collections, all you have to do the BMax way is remove them from those collections. Your way you have to remove them from those collections and delete them.
Crashing with an error message is always better than silently ignoring a problem which may easily become a debugging nightmare in the future.
I guess that depends how often it happens. If it's a big obvious one that makes you say "whoops, what a dink I am, I forgot to destroy that", then sure. If it's a little doozy that hides away deep in the program, it occasionally crashes on the user, giving them a very bad impression of your program. Whereas the BMax way, it occasionally uses a bit more memory than it really needs. And they'll just blame Windows for that anyway XD
Isn't "removing it from your collection" synonymous with "set all references to it to null"?
No. The .NET gc doesn't use a reference counting system. Its all based on roots and if an object is reachable.
Say object A references object B which references object C. Just for fun, object C references object A.
a-->b-->c ^ | |_______|
These were all local to a function, but we've now exited out of that function. We can no longer reach any of them. Next time a garbage collection happens, all 3 objects are eligable for collection since they are no longer rooted.
We created 3 objects, with cyclic references even.... but nothing had to be explicitly nulled or deleted.
in real-time programming you need things to happen exactly when and how you want. No "waiting for the garbage collection to kick in".
As far as games or graphics programming goes, what does it matter if a sprite/bullet/whatever is deleted at precisely the moment you stop using it? How will that negatively effect the execution of your program?
I mean really think about it. Your program isn't going to run slower or incorrectly because you have dead objects sitting in the heap.
it introduces a lot of complexity in how objects are created/destroyed.
Like in the first example, just drop your garbage on the floor and be done with it..it'll get cleaned up. Thats one of the beautiful things about .NET.
The garbage collector is pretty efficient in practice. Its self tuning, and allocation based. When you create new objects and fill up more of the heap, the more likely it will kick into action. But if you're not allocating anything -- the gc is essentially asleep.
So someone will point out -- "but you're always creating new objects!" Which is true, but you have to remember that in .NET a good portion of what you work with are valuetype's, like int, float, or user defined structs. These all live on the stack, or are embedded into other objects. They have none of the overhead involved with garbage collection.
Is the gc perfect? Not quite ;)
In general, any managed object will get cleaned up as needed, but theres a gotcha when it comes to delegates and events. Those *can* leak.
The gc has no say over unmanaged code, so alot of the time when you interact with native libraries, you have to implement the Dispose pattern for deterministic clean up.
When it comes to doing work with pointers, you have a slight hassle of having to pin objects in place, so the gc wont move your object, and invalidate your pointers.
Like in the first example, just drop your garbage on the floor and be done with it..it'll get cleaned up. Thats one of the beautiful things about .NET.
In general, any managed object will get cleaned up as needed, but theres a gotcha when it comes to delegates and events. Those *can* leak.
That's nice, I'm glad they've got garbage collection working so well, but I don't disagree with that. I simply said that I dislike the GC programming style.
As far as games or graphics programming goes, what does it matter if a sprite/bullet/whatever is deleted at precisely the moment you stop using it? How will that negatively effect the execution of your program?
Sprites and bullets really don't make any difference, but if you're building a dynamic geometry paging system (similar to windows virtual RAM, but with 3D data) for your game engine (like I am), having that extra level of control really helps.
How can it be more? If the only place your objects exist is in their collections, all you have to do the BMax way is remove them from those collections. Your way you have to remove them from those collections and delete them.
I could give a few code examples, but the real "work" is not in the typing, but in getting everything to work as you expect it to. For example, I had a bit of trouble getting MaXML to avoid circular references in order for everything to work properly.
I guess that depends how often it happens. If it's a big obvious one that makes you say "whoops, what a dink I am, I forgot to destroy that", then sure. If it's a little doozy that hides away deep in the program, it occasionally crashes on the user, giving them a very bad impression of your program. Whereas the BMax way, it occasionally uses a bit more memory than it really needs. And they'll just blame Windows for that anyway XD
I'm not sure what you point is, but I still prefer a descriptive error message (C++ way) over a plain crash (BlitzMax way).
In my example, if C++ tried to execute "delete tank; tank.Shoot();", you would get an error describing that tank you want to shoot does not exist.
In BlitzMax, if you tried to execute "tank.Free(); tank.Shoot();", it would simply crash somewhere in tank.Shoot(), as it's trying to do something after tank.Free() has basically Nulled everything out. Of course, there are cases where tank.Shoot() would run without an error (which would be even worse, potentially causing errors to pop up randomly in other locations, all because one error wasn't properly caught earlier), but chances are that tank.Shoot() is going to crash with a very unhelpful error message.
Either way, it's certainly not helping you debug a program, and personally I like to make bug-free programs over bug-hidden programs.
Sprites and bullets really don't make any difference, but if you're building a dynamic geometry paging system (similar to windows virtual RAM, but with 3D data) for your game engine (like I am), having that extra level of control really helps.
Do you know this is really a problem yet?
A common mistake of a lot of programmers is their "I must pre-optimize everything" mindset.
You never know distinctly how the compiler is going to translate your source.
I'd recommend you get it working, then run a profiler to find the real bottlenecks.
I could give a few code examples, but the real "work" is not in the typing, but in getting everything to work as you expect it to. For example, I had a bit of trouble getting MaXML to avoid circular references in order for everything to work properly
As Orca mentioned earlier, this has to do with the method that the GC is implemented in Max (reference count vs. rooted)
A circular referenced item will never cycle it's reference count down to 0, which keeps it alive unless you give the compiler a hint.
In my example, if C++ tried to execute "delete tank; tank.Shoot();", you would get an error describing that tank you want to shoot does not exist.
I might be mistaken here, but I don't think that's the way C++ handles exceptions on a production build (i.e. minus debugger mappings)
That's no excuse to use inefficient code.
Inefficient is a matter of perspective. Bug hunting for that one rogue pointer for three months, to me, simply isn't worth the hassle of getting any real or imagined marginal performance boost. What matters to me is "When can we ship it", and if automatic GC means we can ship three months earlier, then that's what we're going to do. Although as soon as you start using multiple threads (as many games now are doing), you lose that boost.
Not really. There is plenty of idle CPU time to go around - in a pre-emptive multitasking OS, you're going to have context switches every n times a second anyway, might as well get something out of it. now you must create your own custom "deleter" functions, which can be very inconsistent between code libraries.
No you must not. That's the beauty of managed code! Sure there are still certain (legacy) instances where you need to dispose and object (streams and pretty much everything related to Win32) - but with time, hopefully that'll soon be a thing of the past. At least in C++ it will tell you that you're trying to access an object that doesn't exist (sure makes sense to me)
What C++ are we talking about here? CodeWarrior, Visual C++ and Borland C++ don't throw any errors when accessing a rogue pointer, because being an unmanaged language, it doesn't know (or care) that the object doesn't exist. They will all gladly execute whatever code just happens to be where your objects shoot method used to be - giving the CPU an illegal instruction, if you're lucky, or just executing random instruction if you're not so lucky.On the other hand, BlitzMAX (or any other managed language like C# or Java) will give you a NullPointerException, telling you that the object you tried referencing, doesn't exist.
Inefficient is a matter of perspective. Bug hunting for that one rogue pointer for three months, to me, simply isn't worth the hassle of getting any real or imagined marginal performance boost. What matters to me is "When can we ship it", and if automatic GC means we can ship three months earlier, then that's what we're going to do.
If GC takes months off your development time, then absolutely you should use it. Personally, I am much more productive in C++.
A common mistake of a lot of programmers is their "I must pre-optimize everything" mindset.
Just how is this a mistake? I understand how you can easily get caught up in optimizations in the beginning, but there's a certain point where you must plan ahead and determine exactly how much optimization you need.
I optimized BattleTanks II fairly well completely from the beginning, and I've had no problems during the development of that game, and it runs very smoothly even on older PCs. I'd love to know how this is a mistake.
As Orca mentioned earlier, this has to do with the method that the GC is implemented in Max (reference count vs. rooted)
A circular referenced item will never cycle it's reference count down to 0, which keeps it alive unless you give the compiler a hint.
A circular referenced item will never cycle it's reference count down to 0, which keeps it alive unless you give the compiler a hint.
Ok, that makes sense.
What C++ are we talking about here? CodeWarrior, Visual C++ and Borland C++ don't throw any errors when accessing a rogue pointer, because being an unmanaged language, it doesn't know (or care) that the object doesn't exist.
Ok, I just tried this in Visual C++, and you're right - it doesn't say an object doesn't exist for a rogue pointer. I'm not sure why I thought otherwise, maybe I was thinking of managed C++ :)
So, revising my example above:
BlitzMax "tank.Free(); tank.Shoot();" - consistent random bug
C++ "delete tank; tank.Shoot();" - inconsistent random crash
I can see how tracking down a rogue pointer might be a problem. Thanks for pointing this out, FlameDuck.
Probably the reason I was wrong about C++ detecting rogue pointers is that I rarely (if ever) encounter them. It may seem strange to you, but I can't even remember the last time I had any trouble with pointers whatsoever. With proper design, you can avoid these problems.
But that's besides the point - FlameDuck is correct here - managed languages are better for rogue pointer detection.
However, my original point remains: managed or unmanaged, a language which does not allow the use of "delete" results in more confusing and complicated code (IMHO). Apparently this is largely a matter of preference, and obviously my opinion isn't the best one (I'm sure there are several others here who have completed full polished 3D games with a GC language ;) )
Just how is this a mistake?
Well mistake is probably not the best word, but it could potentially have been unnecessary. I suppose it depends on whether you use a "top down" approach to software development or a "bottom up" one. I can see how tracking down a rogue pointer might be a problem.
Oh the horror stories I could tell. It's not so much a problem if you're doing the one man army thing, but once you go above 3 or some programmers working on the source code, you'd be surprised how often one of these babies gets through, even with an experienced team, and reasonably good documentation. managed or unmanaged, a language which does not allow the use of "delete" results in more confusing and complicated code (IMHO).
4 years ago, I would have agreed with you completely. Today however my approach to problem solving is more about finding the right datastructure to solve a problem, as I find it often offers the more elegant and/or flexible solution. Still I don't have any insight to what kind of problems you're normally working with, but I'm sure your approach works just as well. In either case, my nephew really enjoys BT II and is freakishly good at it, so I think you've demonstrated that your way works, regardless of whether I think it's the smart thing to do or not. I'm sure there are several others here who have completed full polished 3D games with a GC language ;)
I think the reason we're not seeing more games written in GC languages is more because many of the companies producing said games have a lot of assets tied up in legacy, unmanaged software. Hopefully XNA will help address some of these issues. I mean the video game industry isn't exactly known for their embrace of new stuff (with the possible exception of graphics hardware). According to Daniel Irish (and I'll take his word for it), most companies are still using code & fix as their development process. Which is just sad, I reckon.Sorry about the rant BTW.
Well mistake is probably not the best word, but it could potentially have been unnecessary. I suppose it depends on whether you use a "top down" approach to software development or a "bottom up" one.
Yes. I agree. Mistake is probably a harsh word. Please accept my apologies.
As Flameduck eluded to, you're probably doing something that's unnecessary.
How can you optimize a bottleneck when you're not even sure one exists? As I mentioned in my original post. Be sure it's a problem before you spend time on it. I've seen many situations where the pre-optimized code, while looking real slick and engineerish, actually is less performant than the straightforward way. Why? Because the compiler recognized the straight-forward way and proceeded to emit code that works better.
This is especially important for JIT-based frameworks as the type of optimal code to produce will differ from machine to machine and from OS to OS.
Well mistake is probably not the best word, but it could potentially have been unnecessary. I suppose it depends on whether you use a "top down" approach to software development or a "bottom up" one.
I actually use a combination of both, where everything is kept object oriented and optimized reasonably.
Oh the horror stories I could tell. It's not so much a problem if you're doing the one man army thing, but once you go above 3 or some programmers working on the source code, you'd be surprised how often one of these babies gets through, even with an experienced team, and reasonably good documentation.
You're probably right - I haven't had much experience working on a team, so I wouldn't know. But it seems that in the professional industry there must be some method used to keep these problems to a minimum, or is it just a coincidence maybe that I never read anything about these horror stories from the "professionals" of the industry?
I think the reason we're not seeing more games written in GC languages is more because many of the companies producing said games have a lot of assets tied up in legacy, unmanaged software. Hopefully XNA will help address some of these issues. I mean the video game industry isn't exactly known for their embrace of new stuff (with the possible exception of graphics hardware). According to Daniel Irish (and I'll take his word for it), most companies are still using code & fix as their development process. Which is just sad, I reckon.
That's a good point. Companies usually like to avoid large scale changes, even if they offer a few advantages.
But also, in the gaming industry, speed is often a big issue. I'm no expert on how other languages compare to C++ in terms of speed, but I have played some Java games on my high-end machine, and they run rather slow. If you were a company developing a high-tech engine like CryEngine 2, you'd probably choose C++ too, since you definitely need every bit of power you can get.
I may be a little paranoid, but it seems that it's a shame to let all the amazing features of modern processors go to waste due to unoptimized languages.
As Flameduck eluded to, you're probably doing something that's unnecessary.
How can you optimize a bottleneck when you're not even sure one exists? As I mentioned in my original post. Be sure it's a problem before you spend time on it.
How can you optimize a bottleneck when you're not even sure one exists? As I mentioned in my original post. Be sure it's a problem before you spend time on it.
You don't need a bottleneck to optimize something. On a single-core CPU, you have a certain number of processor cycles available per frame before you create a CPU bottleneck. Optimizing early on (everywhere) really helps when you start adding intensive tasks like A* and real-time line-of-sight calculations.
I've seen many situations where the pre-optimized code, while looking real slick and engineerish, actually is less performant than the straightforward way. Why? Because the compiler recognized the straight-forward way and proceeded to emit code that works better.
This is especially important for JIT-based frameworks as the type of optimal code to produce will differ from machine to machine and from OS to OS.
This is especially important for JIT-based frameworks as the type of optimal code to produce will differ from machine to machine and from OS to OS.
True, but this depends on what you call "optimize". I call "optimize" the process of making your code run faster. If that means avoid seemingly elegant solutions due to better overall JIT results, then that's optimization too.
You don't need a bottleneck to optimize something. On a single-core CPU, you have a certain number of processor cycles available per frame before you create a CPU bottleneck. Optimizing early on (everywhere) really helps when you start adding intensive tasks like A* and real-time line-of-sight calculations.
I disagree. It is far easier to make a correct program fast than a fast program correct. I assure you. I'm not making up the approach at all.
And if you want to get technical, it probably has less to do with the CPU itself and more to do with the amount and type of cache that CPU has, which is again, something the JIT may take into consideration when it emit's it's native code.
This also becomes important once you get into a situation where you have a team of developers. In this situation, code clarity is far more important up front than how fast it is. You can attack that problem later. This is why they invented profilers.
True, but this depends on what you call "optimize". I call "optimize" the process of making your code run faster. If that means avoid seemingly elegant solutions due to better overall JIT results, then that's optimization too.
What is "faster"? Performance is about how the user perceives the responsiveness. Not always about how many cycles you're saving.
I like Garbage collection.
Thats my comment. Nothing to add. Dead objects are just something that I never worried about when I was little, was told to worry about at collage, and now dont have to worry about any more. I can see JohnJs point, but the whole deleting the object thing is just somthing they added to make programming more difficult than it used to be. And now "they" have thought about it, and we dont have to do it anymore.
And functions Ha, they are just gosubs to labels.
Thats my comment. Nothing to add. Dead objects are just something that I never worried about when I was little, was told to worry about at collage, and now dont have to worry about any more. I can see JohnJs point, but the whole deleting the object thing is just somthing they added to make programming more difficult than it used to be. And now "they" have thought about it, and we dont have to do it anymore.
And functions Ha, they are just gosubs to labels.
And functions Ha, they are just gosubs to labels.
If you look at the assembly language emitted by the compiler, that's exactly what it is (most of the time). :)
Point is, the compiler decided if it was most efficient to set aside a block of labeled code, or just in-line it. If you in-line it all yourself, you don't give the compiler the opportunity to optimize the code (JIT might decide to go with a code block if the machine has low memory, or in-line it if there's memory to spare).
What is "faster"? Performance is about how the user perceives the responsiveness. Not always about how many cycles you're saving.
Of course, the whole point is making the game seem smooth and responsive on all possible machines. There's only one way that I know of to increase smoothness and responsiveness on all possible machines: decreasing the amount of time per frame. Please let me know of any other ways you might know of :)
In this situation, code clarity is far more important up front than how fast it is.
In C++ at least, code can be optimized fairly well without sacrificing readability. When I refer to optimization, I'm more referring to a level of optimization beyond the compiler: no compiler can decide whether or not to use impostors, for example, or whether their batches should use a vertex shader or dynamic vertex buffers.
And if you want to get technical, it probably has less to do with the CPU itself and more to do with the amount and type of cache that CPU has, which is again, something the JIT may take into consideration when it emit's it's native code.
True. When I optimize lines of code, it's more a matter of avoiding unnecessary logic (maybe rearranging ifs on a scale of importance), taking helpful shortcuts which an optimizer would never "think" of, and exploiting knowledge about the optimizer/CPU that I know will help.
There's a certain point where compilers can no longer optimize, and the only way to improve performance is to consider optimizations yourself. Compiler optimization is very good for micro-level optimizations (at the assembly level), but there is no way compilers will ever be able to recognize and reason out every possible improvement of code.
For example, if I was going to calculate if distance < max, I would not do this:
float distance = Math::Sqrt(x*x + y*y + z*z); if (distance < max) { ... }
I would do this instead:
float distanceSq = x*x + y*y + z*z; float maxSq = max*max; if (distanceSq < maxSq){ ... }
Compilers may some day be able to recognize and optimize the first example here, but this is only one out of millions of possible mis-optimizations which a little common optimization sense can fix easily and cleanly.
It is far easier to make a correct program fast than a fast program correct.
I understand what you're saying, but I do not consider "bloated code" as "correct" when applied to games.
Note that I am a "modular" programmer and I will always prefer a good expansible structure over a messy monolithic "optimized" main loop. I try not to sacrifice structure for performance, but there is a certain point you have to draw the line for game development. I see no reason why you can't have a good balance of both performance and structure.
But it seems that in the professional industry there must be some method used to keep these problems to a minimum
There is. Only let a small group (core programmers) do the C++ thing. Everyone else gets to use Lua or Python for the game itself (ie things that aren't that speed critical). In C++ at least, code can be optimized fairly well without sacrificing readability.
Well that's certainly a matter of opinion. C++ was designed in such a way as to reuse as much of the existing C syntax, which can make C++ statements somewhat ambiguous as to their function.I used to have this discussion all the time 10 years ago, except then it was Assembly vs. C++. Today I doubt you'll personally know ten people who bother writing programs in assembly (unless you happen to be Steve Gibson). In a couple more years, the same will be true for C++, I assure you.
C++ was designed in such a way as to reuse as much of the existing C syntax, which can make C++ statements somewhat ambiguous as to their function.
C++ certainly isn't perfect, and I understand that some syntax is a little ambiguous. It's really less of a language trait, and more of a design trait. Either way, I can optimize things fairly well while retaining readable code.
I used to have this discussion all the time 10 years ago, except then it was Assembly vs. C++. Today I doubt you'll personally know ten people who bother writing programs in assembly (unless you happen to be Steve Gibson).
I doubt anyone seriously tries to program 100% in assembly, but it still has it's place: inline. You can embed small portions of assembly code in a C++ application to make sure time-critical bottlenecks are 100% optimized. In fact, I may even do this in my project unless I decide to go cross-platform.
In a couple more years, the same will be true for C++, I assure you.
I don't know. Moving from assembly to C++ is a huge step, but C#/Java/Python/etc. really isn't that much of a improvement. I know it offers managed code and everything, but that's nothing compared to assembly vs. C++.
But in 10 years processors will probably be so fast that it won't matter, so maybe you're right. Maybe optimization will be a thing of the past, but somehow I doubt it.
In summary: given the choice of developing a game in C#/Java/Python/etc. that runs at unplayable frame rates, and C++ at playable frame rates, I would choose C++.
P.S. Try MS Flight Simulator X if you want to get an idea what can happen if you neglect your optimizations. My high-end gaming PC can barely run that game at 10-20 FPS (and the graphics are nothing special), where almost any other high-tech game runs above 60-100 FPS.
I still can't believe C++ is that popular when you can code Objective-C. Well, I guess C++ simply sounds cooler...
I still can't believe C++ is that popular when you can code Objective-C. Well, I guess C++ simply sounds cooler...
Is Objective-C fast? Is it easy to program in and bebug, enough so to make it worthwhile? It is cross-platform?
I haven't looked much into Objective-C, but is it really that much superior to C#/C++/other languages?
P.S. Whoa... it looks like this thread has really gotten off-topic. Who would have thought that this was originally an XNA thread? :)
Objective-C is fast, it's easy to program and debug (Cocoa is build upon it) and thanks to GNUstep it's also cross-platform. It's an other approach to object oriented programming but it's easier to pick up than C++ and the line that seperates Objective-C from C is much clearer.
P.S. Try MS Flight Simulator X if you want to get an idea what can happen if you neglect your optimizations.
That's a low blow, and here's one right back at ya. Neverwinter Nights 2. I don't know MSFSX or anything because I don't play boring "games" like flight simulators and spreadsheets, I mean football managers. But sure optimization can be a big deal.However none of us here really knows why, the titles we mention as bad examples of what can go horribly wrong when developers don't think things through, turned out as horribly as they did. If I where a gambling man, I'd say time restraints / pressure from the publisher.
Of course in Microsofts case that didn't work out too well, and in Obsidians case, well they just plain suck - I hope to all the gods they don't get to make Jade Empire 2).
Of course, the whole point is making the game seem smooth and responsive on all possible machines. There's only one way that I know of to increase smoothness and responsiveness on all possible machines: decreasing the amount of time per frame. Please let me know of any other ways you might know of :)
Point taken. BUT.. if you're targetting differing OS's, the way you shave time off a frame for one OS might have adverse effects on another.
That's why I mentioned you should keep the code readable and apply a common pattern. If the compiler doesn't emit fast code and you need to do a compile-directive code branch for a different OS, then at least you'll know what you were attempting to do when you visit that code 3 months later.
I think we just have differing agendas when it comes to design approach. I tend to not worry about the bottlenecks until I know what they are and if they are significantly detrimental.
We can agree to disagree.
I understand what you're saying, but I do not consider "bloated code" as "correct" when applied to games.
I still can't quite figure out what the hang-up is about so-called bloated code. Back when memory was scarse and diskspace about as scarse, it was definitely an issue. Or, if you're targeting a console, I suppose it's a concern as well.
PCs are another story.
The ability to have "larger" files isn't necessarily a bad thing. It allows you to have some expressive code and a layer of abstraction that you couldn't have had before now. Granted sometimes this is abused, but in 2007, it's not nearly the issue that many developers think it is.
Graphics in games now take up significantly more room than they did before as does sound, yet nobody ever complains about how "bloaty" the graphics files are. Why? Because it's acceptable for people to understand that in order for graphics to evolve they need the extra space. So why isn't program code held to that same level of understanding?
P.S. Try MS Flight Simulator X if you want to get an idea what can happen if you neglect your optimizations. My high-end gaming PC can barely run that game at 10-20 FPS (and the graphics are nothing special), where almost any other high-tech game runs above 60-100 FPS.
Again.. as I mentioned above, I'm not saying you should never optimize. I'm just saying you shouldn't pre-optimize. It appears that the Flight Simulator folks neglected it even after the fact.
Or perhaps they pre-optimized to a particular configuration and it ended up biting them in distribution :)
I doubt anyone seriously tries to program 100% in assembly, but it still has it's place: inline. You can embed small portions of assembly code in a C++ application to make sure time-critical bottlenecks are 100% optimized. In fact, I may even do this in my project unless I decide to go cross-platform.
As Flameduck said, at some point, C++ will be the new "Assembly" and be used the same way (last resort in-lining) It's happening now, actually. C++ is a better in-lining choice anyway because it's platform independent.
Point taken. BUT.. if you're targetting differing OS's, the way you shave time off a frame for one OS might have adverse effects on another.
I don't think there's any OS where slow programs results in smoother gameplay on a Von Neumann architecture CPU (basically all PCs). So no matter what OS or ISA you're using faster code = smoother gameplay. Please let me know of any cases where slower code = smoother results.
I still can't quite figure out what the hang-up is about so-called bloated code. Back when memory was scarse and diskspace about as scarse, it was definitely an issue. Or, if you're targeting a console, I suppose it's a concern as well.
Maybe bloated wasn't the right word. I meant ridiculously unoptimized code; I don't care about storage space. Like this:
'Add 1000 to X Local x:String, add:String Local i:Int For i = 1 To 1000 add = "1" x = (Int(x) + Int(add)) Next
Of course, nobody really programs like this, but you'd be surprised how code can often become as blatantly unoptimized like this if you don't optimize "lightly" throughout your code.
Again.. as I mentioned above, I'm not saying you should never optimize. I'm just saying you shouldn't pre-optimize. It appears that the Flight Simulator folks neglected it even after the fact.
Or maybe when they completed it, going back and optimizing everything required such an enormous restructure (basically an entire engine rewrite due to unoptimized design), that it was impossible.
As Flameduck said, at some point, C++ will be the new "Assembly" and be used the same way (last resort in-lining) It's happening now, actually. C++ is a better in-lining choice anyway because it's platform independent.
For platform independent code, yes (if you don't want to write assembly for each platform). For specific platform code, no. In most cases, assembly is never needed, but it's nice to have if you ever come across a serious bottleneck.
But as CPUs get more and more powerful, maybe they will be fast enough, even with all the excess of managed languages, etc. The thing is, unless CPU power is unlimited, there will always be that time where you want just a little more power for just a little more speed (your processor is capable, why not use that capability?) and AFAIK managed languages make that impossible.
I don't think there's any OS where slow programs results in smoother gameplay on a Von Neumann architecture CPU (basically all PCs). So no matter what OS or ISA you're using faster code = smoother gameplay.
That's not exactly true. For instance obtaining a mutex on the UltraSPARC processor is a single instruction, where as on Intel i686 processors it requires flushing the current instruction pipeline. Thus, obtaining a mutex is several orders of magnitude slower on an Intel architecture CPU.Also the code that determines what instructions can be executed in parallel is going to be vastly different, even across similar architectures.
Personally I think that VLIW processors and JIT compilers are the way to go for optimization. Bring on the revolution!
That's not exactly true. For instance obtaining a mutex on the UltraSPARC processor is a single instruction, where as on Intel i686 processors it requires flushing the current instruction pipeline. Thus, obtaining a mutex is several orders of magnitude slower on an Intel architecture CPU.
Ok, but how does this make slower code result in smoother frame rates?
Personally I think that VLIW processors and JIT compilers are the way to go for optimization. Bring on the revolution!
I also think JIT is a very good way to do optimization, but you still can't get away with unoptimized algorithms - no optimizer can fix that.
P.S. When I say "optimized code", I really mean "optimized algorithms" ("code" probably isn't the right word at all). When I refer to optimization, I don't mean crafting your code to produce better machine code (that's the compiler's job) - I mean crafting your algorithms to get the job done as effeciently as possible.
Unless AI with superhuman IQs can be developed, I doubt any optimizer will be able to flawlessly rewrite your algorithms more efficiently; that's what good programmers are for.
P.S. When I say "optimized code", I really mean "optimized algorithms" ("code" probably isn't the right word at all). When I refer to optimization, I don't mean crafting your code to produce better machine code (that's the compiler's job) - I mean crafting your algorithms to get the job done as effeciently as possible.
Ahh.. that explanation plus your extreme example above clarifies things.
What you're describing I wouldn't term as "un-optimized code", but more along the lines of a code smell and misunderstanding of language syntax.
We're probably in agreement more than I originally suspected.
Ok, but how does this make slower code result in smoother frame rates?
Mostly because it's not so much about the CPU anymore, and more about the graphics card-->driver-->API pipeline. The main CPU acts as a proxy between your application and the API, and much of CPU cycles you're seeing after a graphics call are actually empty event polls (i.e. watching the message queue on windows machines) waiting for the API to return a reponse.
Those are at the very least, 3 levels of failure with exponential potential of difference from machine to machine before it even gets to your compiled code.
I've heard a lot of horror stories of contradictive behavior amongst video cards for certain API calls. I think in the early days of Blitz this was a pretty big headache for Mark. Or at least thats what his work logs seemed to suggest.
Mostly because it's not so much about the CPU anymore, and more about the graphics card-->driver-->API pipeline. The main CPU acts as a proxy between your application and the API, and much of CPU cycles you're seeing after a graphics call are actually empty event polls (i.e. watching the message queue on windows machines) waiting for the API to return a reponse.
Maybe for pure graphics rendering, but for games there's a lot more than graphics API calls going on. You have to constantly update physics, audio, controls, AI, etc. Things like physics and AI (when you need line-of-sight calculations) can really bog the CPU down.
In almost every game you make, chances are you're going to reach the limit of your CPU some time and have to back down a little (for example, in BattleTanks II I had to cut out line-of-sight calculations), otherwise frame rate will suffer. Of course, you can always go back and optimize your code when you reach this limit, but there's no sure way of knowing whether your hours and hours of post-optimization will even be able to help enough - that's why I like moderate pre-optimization.
@John,
When,(or if), you are stuck useing a language with GC. Would you turn it off automatic?
That is, are you saying you dont like it when the language does something behind your back with no control as to when. Or are you saying you just hate the idea of letting all the null pointers (or whatever) pile up?
When,(or if), you are stuck useing a language with GC. Would you turn it off automatic?
That is, are you saying you dont like it when the language does something behind your back with no control as to when. Or are you saying you just hate the idea of letting all the null pointers (or whatever) pile up?
H&K: I don't like the inability to use "delete" when I want. When I want to delete a car, I want to delete it, not remove it from a list and hope it's not being used somewhere else.
Ok... but would it really matter if delete just removed the car from your view, and some time latter the flatbed turned up to takeit away.
That is does it matter that what delete actualy does in the background?
I dont think this entire OPtimisation discussion is really about GC likes or dislikes. Because when you optimise a bit of code, one of the things you do is try to minimise the number of deletes or pointers to NULL. How the things are then delt with is a different issue
Also (seprerate question), do you know if the "soft pointer" issue was resoved in BMax? Cos this is something that I think GC in BMax has gotten wrong.
That is does it matter that what delete actualy does in the background?
I dont think this entire OPtimisation discussion is really about GC likes or dislikes. Because when you optimise a bit of code, one of the things you do is try to minimise the number of deletes or pointers to NULL. How the things are then delt with is a different issue
Also (seprerate question), do you know if the "soft pointer" issue was resoved in BMax? Cos this is something that I think GC in BMax has gotten wrong.
Now that I think about it, when you delete an object in C++ you have to rely that it's not being used somewhere else or it will crash, so that aspect is no different than GC. I guess the main thing is that if there's a pointer bug in my program somewhere, I want it to be caught as an error, rather than strange in-game behavior due to objects remaining longer than they should.
In MaXML, I think my main problem was circular references made it such a pain to delete anything. For example, nodes reference documents, and documents reference nodes. To delete a document, you can't just set your variable reference to Null, you have to additionally tell the document to clean itself up, which was somewhat tedious to get working right.
But since FlameDuck says there are better garbage collection methods than BlitzMax's, maybe GC isn't that bad after all. In this case, my only concern would be speed.
Edit: This is an interesting quote from the .NET :
http://msdn2.microsoft.com/en-us/library/ms994405.aspx
In MaXML, I think my main problem was circular references made it such a pain to delete anything. For example, nodes reference documents, and documents reference nodes. To delete a document, you can't just set your variable reference to Null, you have to additionally tell the document to clean itself up, which was somewhat tedious to get working right.
But since FlameDuck says there are better garbage collection methods than BlitzMax's, maybe GC isn't that bad after all. In this case, my only concern would be speed.
Edit: This is an interesting quote from the .NET :
"You may not disclose the results of any benchmark test of the .NET Framework component of the OS Components to any third party without Microsoft's prior written approval."
http://msdn2.microsoft.com/en-us/library/ms994405.aspx
there are better garbage collection methods than BlitzMax's, maybe GC isn't that bad after all. In this case, my only concern would be speed.
Well thats what I was getting at earlier...the .NET collection scheme and blitzmax's are totally different. I've never had any headaches with cyclic references, keeping objects alive, leaking memory, etc while coding in c#( well not with managed objects -- working with native libraries yes ). Worrying about that stuff is non existant to me now..It free's me up to focus on the task at hand.
Obviously there is a cost when a collection is invoked. This cost is driven by the number of live objects, and how many reference type objects they all point to. The gc builds a graph of all reachable objects. Everything else is garbage.
On the desktop, it doesnt collect the whole heap at once. It divides it up based on how old objects are( generations ). Generally, it'll do collections on generation 0, which is where all the youngest objects reside. Younger objects are more likely to die. ( Think about all those local variables you create... )
Generation 0 collections are relatively cheap. Gen 1, and 2 are progressively more expensive.
You can get all kinds of data on managed apps by using windows performance counters and/or using the free ClrProfiler tool from microsoft. Granted I haven't tried running a half life 3, but in my experience.... the gc is pretty amazing and works as advertised. You write good code and don't get sloppy, your % of time in gc can be pretty darn low.
( I should point out that the .NET memory management isn't just about avoiding memory leaks btw-- it actually improves overall performance too... )