【问题标题】:Poor performance on 360 and WP7在 360 和 WP7 上表现不佳
【发布时间】:2012-02-04 17:41:49
【问题描述】:

我刚刚在 360 和 WP7 上运行了我的 2D sprite 游戏,在这些上运行速度比 Windows 慢得多。 FPS 大约是每秒一帧,但在 windows 上它很流畅。我正在使用 Farseer 的最新版本。这两个平台上是否有任何东西可能导致如此急剧的减速?

提前致谢。

【问题讨论】:

  • 这听起来像是在某个地方犯了一些简单的错误。您是否尝试过在 360 上使用 Pix 来查看时间都花在了哪里?
  • 在 SpriteBatch 开始和绘制之间我这样调用: sprites.Draw(Texture, _drawPosition, Texture.SourceRectangle, OliveColor.White, (float)OliveMaths.DegreeToRadian(Angle + 180.0f), _midPoint , 1.0f, 1.0f);

标签: c# windows-phone-7 xna xbox360


【解决方案1】:

是的。这两个平台上肯定有一些事情会导致显着减速。 360 和 WP7 上的 CLR 的垃圾收集器比 PC 上慢得多。因此,这两个平台上的性能可能会有很大差异。在 PC 上以 60 fps 运行的游戏在这些平台上可能会慢到 1-2 fps 秒的爬行速度。

有很多资源可用于故障排除和优化代码以在所有三个平台上获得相同的 FPS。以下是我推荐的。

首先,请查看 Shawn Hargreave 关于“How to tell if your Garbage collection is too slow”的文章,这将首先回答您所看到的是否是这样的。

然后点击“High End Performance Optimizations for Xbox360 and WP7”上的 Ian Nicolades 文章,那篇文章中有很多很好的建议、提示和技巧。其中大部分应该有助于解决您当前遇到的任何性能问题。

这里还有一些关于 Stack Overflow 的好帖子,我建议您仔细阅读: Game Jitters on xBox360 XNA game performance

还有一些好的阅读,.NET Compact 框架团队(WP7 和 360 都运行紧凑框架的修改版本)有一些关于 Xbox 360 上的托管代码性能的旧但很好的文章 Part1 和 @987654326 @

还有一些来自战壕中的人的精彩文章。之前在 360 和 WP7 上发布过游戏的人。这是我最喜欢的 Kris Steele 之一,他使用 XNA 在多个平台上发布了名为“Optimizing Code for Xbox XNA Games is required”的游戏。

最后但并非最不重要的一点是,App Hub 论坛上有大量帖子,涵盖从WP7Xbox 性能的所有领域。不幸的是,App Hub 上的搜索不是很好,但那里的帖子提供了有关如何在这些平台上查找和提高游戏性能的各种提示/技巧和建议。

【讨论】:

  • 感谢您提供的所有信息,事实证明它非常有用。我关注的有两件事,一是在游戏过程中新的对象提高了 FPS。另一个问题是 IsFixedTimeStep 已启用,这不应该启用,但确实产生了巨大影响。
【解决方案2】:

我完全同意 George Clingerman,360 和 WP7 上的 CLR 的垃圾收集器比 PC 上慢得多。

首先,我建议你了解垃圾收集器的工作原理(没那么难)。

基本步骤是: 1. 验证 2. 简介 3. 定位 4. 修复

您可以在此处找到有关如何使用 CLRProfiler http://spacedjase.com/post/2010/07/02/How-to-eliminate-frame-by-frame-Garbage-Generation-using-CLR-Profiler.aspx 进行操作的分步说明(基本)

CLR Profiler 使您能够查看进程的托管堆并调查垃圾收集器的行为。使用工具中的各种视图,您可以获得有关应用程序的执行、分配和内存消耗的有用信息。 (下载http://www.microsoft.com/download/en/details.aspx?id=16273

以下是我在互联网上找到的最有用的链接:

以下是我认为最重要的问题的总结:

不要使用 linq 不要使用 LINQ。看起来很酷。它使您的代码更短、更简单,甚至更易于阅读。但是 LINQ 查询很容易成为垃圾的一大来源。它们在你的启动代码中很好,因为无论如何你只要加载资产和准备游戏资源就会在那里产生垃圾。但不要在 Update、Draw 或任何其他在游戏过程中调用的方法中使用它。

显示字符串而不触发垃圾回收 尽量减少 ToString() 的使用。它至少会创建一个字符串,该字符串位于堆上。有关如何在屏幕上绘制 int 而不产生任何垃圾的信息,请参见上文。如果您确实需要使用 ToString,请尝试限制调用它的频率。如果字符串只在每一关发生变化,则只在关卡开始时生成一次。如果它仅在某个值更改时更改,则仅在该值更改时生成它。您可以设置的任何限制都是值得的。检查布尔条件所需的时间非常短,几乎不存在。在 GC 在复杂堆上运行所需的时间中,您可能会进行数万甚至数十万次真/假检查。 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 注意字符串格式。在不引起分配的情况下,很难在 .NET 中操作字符串。

不要分配内存(呃!) 这很简单:不要在引用类型上调用 new。但是,可以使用新的值类型,例如 Matrix、Vector3 和 Color。 每当您发现自己想要新的引用类型时,请改用对象池来重用现有实例。 oncreators.xna.com 上的粒子和音频 3D 样本使用了这种技术,SwampThingTom 在博客中介绍了一个可重复使用的池集合。 http://swampthingtom.blogspot.com/2007/06/generic-pool-collection-class.html http://spacedjase.com/post/2010/07/02/Generic-Resource-Pool.aspx

不要使用代表您分配的类 当您将数据添加到 List 或 Dictionary 等集合类时,这可能需要分配内存来扩展集合。您可以通过使用具有显式容量参数的集合构造函数重载来避免这种情况。指定一个容量,以便为您打算在集合中存储的最大对象数预分配尽可能多的内存。

不要让 CLR 运行时分配 CLR 运行时在发生装箱时分配内存。像瘟疫一样避免这种情况!拳击的发生有很多原因,有些是显而易见的,有些则不太明显: • 如果将值类型分配给对象变量,它会被装箱。 • 如果您将值类型存储在旧的非泛型集合类之一中,它们将被装箱。 • 通过接口访问值类型会导致它们被装箱。 • 如果使用枚举类型作为字典键,内部字典操作将导致装箱。您可以通过使用整数键来避免这种情况,并在将枚举值添加到字典之前将它们转换为整数

来自阿根廷的问候 赫尔南

【讨论】:

    猜你喜欢
    • 2017-10-01
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 2023-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多