Poor performance on 360 and WP7

2019-05-19 04:47发布

问题:

I've just got my 2D sprite game running on the 360 and WP7 and it's far slower on these than the Windows counterpart. The FPS is about a frame a second, but on windows its smooth. I'm using Farseer the latest version in this. Is there anything on these two platforms that could cause such a drastic slowdown?

Thanks in advance.

回答1:

Yes. There are DEFINITELY things on those two platforms that can cause significant slowdowns. The CLR on the 360 and WP7 have much slower garbage collectors than on the PC. As a result, performance on those two platforms can vary dramatically. A game running at 60 fps on the PC can slow to a 1-2 fps second crawl on those platforms.

There are a lot of resources out there for trouble-shooting and optimizing your code to gain the same FPS across all three platforms. Here are the ones I would recommend.

First, check out Shawn Hargreave's article on "How to tell if your Garbage collection is too slow" That will first answer whether that is what you are seeing.

Then hit Ian Nicolades article on "High End Performance Optimizations for Xbox360 and WP7" There is a lot of good advice, tips and tricks in that article. Most of which should help clear up any current performance issues you're having.

There's also some good posts here on Stack Overflow I'd recommend you peruse: Game Jitters on xBox360 XNA game performance

Also for some good reading, the .NET Compact framework team (both WP7 and the 360 run a modified version of the compact framework) have some oldie but goodie articles on Managed Code Performance on the Xbox 360 Part1 & Part2

There's also some great articles on this from the guys in the trenches. People who have previously released games on the 360 and WP7. Here's one of my favorites from Kris Steele who has released games on multiple platforms with XNA called "Optimizing Code for Xbox XNA Games is required".

And then last but not least, there are a TON of posts on the App Hub forums covering all areas of performance from WP7 to Xbox performance. The unfortunate thing is that the search on the App Hub isn't too great, but the posts are there and offer all sorts of tips/tricks and advice on how to find and improve your games performance on those platforms.



回答2:

I totally agree George Clingerman, the CLR on the 360 and WP7 have much slower garbage collectors than on the PC.

First of all, I recommend you to learn how garbage collector works (it's no so hard).

The basic steps are: 1. Verify 2. Profile 3. Locate 4. Fix

Here you can find step by step instructions (basic) on how to do it with CLRProfiler http://spacedjase.com/post/2010/07/02/How-to-eliminate-frame-by-frame-Garbage-Generation-using-CLR-Profiler.aspx

CLR Profiler enables you to look at the managed heap of a process and investigate the behavior of the garbage collector. Using the various views in the tool, you can obtain useful information about the execution, allocation, and memory consumption of your application. (Download http://www.microsoft.com/download/en/details.aspx?id=16273)

Here are the most useful links I found on the internet:

  • How to tell if your Xbox garbage collection is too slow (http://blogs.msdn.com/b/shawnhar/archive/2007/06/29/how-to-tell-if-your-xbox-garbage-collection-is-too-slow.aspx)
  • Twin paths to garbage collector nirvana (2 different aproachs to fight against slow GC) http://blogs.msdn.com/b/shawnhar/archive/2007/07/02/twin-paths-to-garbage-collector-nirvana.aspx

And heres a summary of what I think are the most significant problems:

Dont use linq Do not use LINQ. It looks cool. It makes your code shorter, simpler, and perhaps even easier to read. But LINQ queries can easily become a big source of trash. They’re fine in your startup code since you’re going to generate trash there anyway just by loading assets and preparing game resources. But don’t use it in Update, Draw, or any other method that gets called during gameplay.

Displaying a string without triggering garbage collection Reply Quote Minimize use of ToString(). At a minimum it creates a string, which lives on the heap. See above about how to draw an int to the screen without generating any garbage. If you do need to use ToString, try to limit how often it’s called. If the string only changes every level, only generate it once at the beginning of the level. If it only changes when a certain value changes, only generate it when that value changes. Any limits you can put are worth it. The amount of time it takes to check a boolean condition is so small as to be almost nonexistent. You could probably fit tens and even hundreds of thousands of true/false checks in the amount of time it can take the GC to run on a complex heap. http://forums.create.msdn.com/forums/p/45512/273330.aspx#273330 http://spacedjase.com/post/2010/09/16/Garbage-safe-number-to-string-conversion.aspx Beware of string formatting. It is hard to manipulate strings in .NET without causing allocations.

Don't allocate memory (duh!) This is simple: do not call new on reference types. It is ok to new value types such as Matrix, Vector3, and Color, however. Any time you find yourself wanting to new a reference type, use an object pool to reuse existing instances instead. The Particle and Audio 3D samples oncreators.xna.com use this technique, and SwampThingTom blogged about a reusable pool collection. http://swampthingtom.blogspot.com/2007/06/generic-pool-collection-class.html http://spacedjase.com/post/2010/07/02/Generic-Resource-Pool.aspx

Don't use classes that allocate on your behalf When you add data to a collection class such as List or Dictionary, this may have to allocate memory to expand the collection. You can avoid that by using the collection constructor overloads which have explicit capacity parameters. Specify a capacity to preallocate as much memory as you will ever need for the maximum number of objects you intend to store in the collection.

Don't make the CLR runtime allocate The CLR runtime allocates memory when boxing occurs. Avoid this like the plague! Boxing can happen for many reasons, some obvious, others less so: • If you assign a value type to an object variable, it gets boxed. • If you store value types in one of the old non-generic collection classes, they will be boxed. • Accessing value types via an interface causes them to be boxed. • If you use an enum type as a dictionary key, internal dictionary operations will cause boxing. You can avoid this by using integer keys, and casting your enum values to ints before adding them to the dictionary

Greetings from Argentina HERNAN