7

我一直在为使用 XNA 构建的游戏进行 C# 优化方面的大量研究,但我仍然不太了解局部变量是否是实例变量,在不断更新和使用时会提供更好的性能。

根据http://www.dotnetperls.com/optimization,您应该避免使用参数和局部变量,这意味着实例变量是性能方面的最佳选择。

但是不久前,我在另一篇 StackOverflow 帖子上读到(我似乎找不到它在哪里),局部变量存储在内存的一部分中,访问速度要快得多,并且每次设置实例变量时,在分配新值之前,必须先删除以前的值,这是一个繁琐的额外步骤。

我知道在设计方面,在这种情况下使用实例变量可能会破坏封装,但我对性能非常好奇。目前在我的游戏中,我将局部变量传递给类中 7 个方法中的 3 个,但我可以轻松地将变量提升为实例变量,并且能够完全避免参数传递和局部变量。

那么哪个会更好呢?

4

3 回答 3

2

您的变量是引用(类或字符串)还是值(结构)类型?

对于引用类型,将它们作为方法参数传递和将它们保存在对象实例上之间没有有意义的区别。在第一种情况下,当输入函数时,参数(对于具有少量参数的函数)最终会出现在寄存器中。在第二种情况下,引用作为“this”在内存中指向的数据的偏移量存在。任何一种情况都是快速获取内存地址,然后从内存中获取相关数据(这是昂贵的部分)。

对于值类型,对于某些类型(可以放入 CPU 寄存器的整数或浮点数),上述情况是正确的。对于那些特定的东西,按价值传递可能比从“这个”中提取它们要便宜一些。对于其他值类型(DateTime 或您可能自己创建的结构或具有多个成员的任何结构),当数据太大而无法通过寄存器传递时,这不再重要。

但是,这不太可能对您的应用程序(甚至是游戏)的性能很重要。最常见的 .NET 性能问题(不仅仅是低效的算法)将以某种形式来自垃圾生成。这可能通过意外装箱、字符串构建使用不当或对象生命周期管理不佳(您的对象的生命周期既不是很短也不是很长/永久)来表现出来。

于 2012-07-27T09:17:24.577 回答
2

就个人而言,我不会将此视为性能问题的罪魁祸首(除非您不断通过大structs)。我幼稚的理解是 GC 压力是 XNA 游戏的通常考虑因素,因此基本上对您的对象实例进行节俭。

如果变量是方法本地的,则值本身或引用(当引用类型时)将位于堆栈上。如果您将它们提升为类成员变量,它们将位于堆上的类内存中。

方法调用在技术上会变得更快,因为您不再在调用中复制引用或值(因为如果方法也是类的本地方法,您可能可以从方法中删除参数)。

我不确定相对性能,但在我看来,如果你需要保持这个值,那么这个值在课堂上是有意义的......

对我来说,两者之间的细微差异似乎超过了做一个有利于另一个的任何潜在收益 - 使它们大致相等或差异如此之小以至于不在乎。

当然,面对来自性能分析的硬数据,所有这些都将得到纠正。

于 2012-07-27T08:45:04.440 回答
1

不传递参数会稍微快一些,不初始化本地对象(如果它们是对象)会更快。

您在两篇文章中读到的内容并不矛盾,一篇提到传递参数需要时间,另一篇提到初始化对象(在本地对象中)也可能需要时间。

关于分配新对象,您可以做的一件事是重用对象而不是丢弃它们。例如,前段时间,我不得不为交易者编写一些代码,用 C/C++ 和 C# 实时计算一些产品的价格。通过不从头开始重新创建方程系统,而仅通过从以前的系统逐步更新系统,我获得了性能的重大提升。

这避免了为新对象分配内存、初始化新对象,而且系统通常几乎相同,因此我只需修改微小的位来更新它。

通常,在进行任何优化之前,您要确保您正在优化会显着影响整体性能的东西?

于 2012-07-27T08:46:46.017 回答