简体   繁体   English

PC XNA游戏转换为Xbox 360 - 巨大的性能问题

[英]PC XNA Game converted to Xbox 360 - Huge Performance Issues

So I wanted to convert my PC game to work on the Xbox 360. It ran damn fine on the PC, with a Intel Core 2 Quad @ 2.40Ghz and a Radeon 4850 512MB. 所以我想将我的PC游戏转换为在Xbox 360上运行。它在PC上运行得非常好,配备Intel Core 2 Quad @ 2.40Ghz和Radeon 4850 512MB。

I ported it to the Xbox, and right off the bat, there was some problem with invariance and inheritance regarding importing of lists, so I simply used the LINQ method called .Cast<>(). 我把它移植到Xbox上,然后关于导入列表,有一些关于导入列表的不变性和继承问题,所以我只使用名为.Cast <>()的LINQ方法。

If that method is takes a big overhead, let me know, because I cannot deploy Performance Analysis on the 360 for some reason, most likely because it plays on the 360. 如果这个方法需要很大的开销,请告诉我,因为我无法在360上部署Performance Analysis,原因很可能是因为它在360上播放。

Then another problem came, and it was a nice System.OutOfMemoryException. 然后又出现了另一个问题,这是一个很好的System.OutOfMemoryException。 My skybox textures were 4096x4096, so reducing them by half removed that error. 我的天空盒纹理是4096x4096,所以将它们减半就消除了这个错误。 Odd though, they were only 3MB x 6, so it shouldn't be using that much of the 512MB available. 奇怪的是,它们只有3MB x 6,所以不应该使用512MB的那么多。

So when all those problems were cleared out of the way, a nice 1 frame per 2 seconds were introduced. 因此,当所有这些问题都被清除时,每2秒引入一个漂亮的1帧。 It then crashes after 1 minute of gameplay, a "Code 4" whatever that means. 然后它在游戏1分钟后崩溃,“Code 4”无论那意味着什么。

It plays like a powerpoint. 它就像一个powerpoint。 Here are some performance analysis images from PC gameplay. 以下是来自PC游戏玩法的一些性能分析图像。 They are not bad. 他们还不错。

CPU: http://i.imgur.com/JYx7Z.png RAM: http://i.imgur.com/C29KN.png And 72% = 150MB mind you. CPU: http//i.imgur.com/JYx7Z.png内存: http//i.imgur.com/C29KN.png 72%= 150MB请注意。

I hope anyone here has some experience on this issue. 我希望这里有人在这个问题上有一些经验。 Frankly I am all ears. 坦率地说,我全都是耳朵。

The root cause of your performance problems is almost certainly because you're allocating memory while your game is running (after startup, during the Draw / Update loop). 您的性能问题的根本原因几乎可以肯定是因为您在游戏运行时(启动后,在Draw / Update循环期间)分配内存。

On Windows this is fine. 在Windows上这很好。 The garbage collector on Windows is generational (will only clean up new objects when possible) and extremely fast. Windows上的垃圾收集器是世代的(只在可能的情况下才会清理新对象)并且非常快。 It is clever about when it chooses to run, too. 关于什么时候选择跑步也很聪明。

The garbage collector on the Xbox 360, on the other hand, is completely rubbish. 另一方面,Xbox 360上的垃圾收集器完全是垃圾。 It runs for every 1MB of memory allocated. 它运行分配的每1MB内存。 It checks the entire managed heap when it runs. 它在运行时检查整个托管堆。 And it's quite slow to boot. 而且启动速度很慢。

So the answer is to never allocate memory while your game is in its running state. 所以答案是在游戏处于运行状态时永远不要分配内存。

There's a good blog post about this here . 这里有关于此的好文章。 (It also describes the alternative to never allocating memory - which is to reduce heap complexity - which is really very difficult to implement and I don't recommend it.) (它还描述了永不分配内存的替代方案 - 这是为了减少堆复杂性 - 这实际上非常难以实现,我不推荐它。)

  • You will have to remove things like LINQ, as the query objects it creates are heap objects, as are the delegates it frequently requires. 您将不得不删除LINQ之类的东西,因为它创建的查询对象是堆对象,它经常需要的代理也是如此。 Use simple loops instead. 请改用简单的循环。
  • If you are allocating your own reference types in draw/update, you will have to convert to using value types where possible or add object pooling. 如果要在绘制/更新中分配自己的引用类型,则必须尽可能转换为使用值类型或添加对象池。
  • Creating string objects is another common source of memory allocations - instead you can re-use a StringBuilder and render that directly. 创建string对象是内存分配的另一个常见来源 - 相反,您可以重新使用StringBuilder并直接呈现它。
  • Converting things (especially: numbers) to strings, even for StringBuilder will allocate memory. 将事物(特别是:数字)转换为字符串,即使对于StringBuilder也会分配内存。 You need to write/find allocation-free alternatives. 您需要编写/查找无分配的替代方案。 My answer to this similar question has one for int . 我对这个类似问题的回答有一个用于int

The best way to diagnose where you are allocating memory is to run your game with the CLR Profiler on Windows. 诊断分配内存的最佳方法是在Windows上使用CLR Profiler运行游戏。 This will tell you where and when memory is being allocated. 这将告诉您何时何地分配内存。 Simply optimise until you're not allocating. 只需优化,直到您不分配。

(Or until you're reliably allocating less than 1MB per level/map/room/whatever, and do a manual GC during a time where it's appropriate to stutter - like a static loading screen or a fade-to-black.) (或者直到你可靠地为每个级别/地图/房间/任何东西分配少于1MB,并在适合口吃的时候进行手动GC - 如静态加载屏幕或淡入黑色。)

Code 4 is an Unhandled Exception. 代码4是未处理的异常。 You need to install a top-level exception handler that outputs a message, or run your game in the debugger, to determine the cause. 您需要安装一个顶级异常处理程序来输出消息,或者在调试器中运行您的游戏,以确定原因。

Finally: That is probably the compressed size of your textures (using PNG or JPEG or similar). 最后:这可能是纹理的压缩大小(使用PNG或JPEG或类似)。 If your textures are uncompressed, 4096 × 4096 × 6 × 4 bytes = 384MB . 如果您的纹理未压缩,则4096×4096×6×4字节= 384MB This is huge - no wonder you ran out of memory. 这是巨大的 - 难怪你的内存不足。 You could compress them with DXT1 and make them 6 times smaller ( instructions , wiki ). 您可以使用DXT1压缩它们并使它们小6倍( 说明维基 )。 You could also reduce their resolution. 你也可以降低他们的分辨率。 And do you need the bottom face at all? 你需要底面吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM