C# ';新';getter中的关键字>;表演命中率?

C# ';新';getter中的关键字>;表演命中率?,c#,performance,xna,new-operator,getter,C#,Performance,Xna,New Operator,Getter,我有以下代码: public class Character { public Vector2 WorldPixelPosition { get { return Movement.Position; } } public Vector2 WorldPosition { get { return new Vector2(Movement.Position.X / Tile.Width, Movement.Position.Y

我有以下代码:

public class Character
{
    public Vector2 WorldPixelPosition
    {
        get { return Movement.Position; }
    }
    public Vector2 WorldPosition
    {
        get { return new Vector2(Movement.Position.X / Tile.Width, Movement.Position.Y / Tile.Height); }
    }
    public Vector2 LevelPosition
    {
        get { return new Vector2(WorldPosition.X % Level.Width, WorldPosition.Y % Level.Height); }
    }
}
现在,在代码的其他地方,我在一个到Character.LevelPosition的循环中进行了大约2500次调用。 这意味着每个更新周期,5000个“新”矢量正在生成,在我的笔记本电脑上,它确实降低了帧率

我通过创建

var levelPosition = Character.LevelPosition;
在我开始循环之前,但每次我遇到类似的情况时,我都会觉得这是一个丑陋的代码。也许这是一条路,但我想确定

有没有更好的或普遍接受的方法来做到这一点


我使用的是XNA框架,它使用的是。

您可以创建一个私有字段来存储值,而不是每次都计算它。您可以创建一个方法来更新私有字段,并以某种方式订阅移动位置更改。这样,当位置改变时,该值将只计算一次。

在循环中创建多个对象可能是一个昂贵的操作(*)。也许if将有助于提前创建
矢量2
(例如,当坐标发生变化时),并且在将来只需更改坐标即可

例如:

public class Character
{
    private Vector2 m_worldPosition = new Vector2(0, 0);
    private Vector2 m_levelPosition = new Vector2(0, 0);

    ....

    public Vector2 WorldPosition
    {
        get
        {
            m_worldPosition.X = ...;
            m_worldPosition.Y = ...;
            return m_worldPosition;
        }
    }

    public Vector2 LevelPosition
    {
        get
        {
            m_levelPosition.X = ...;
            m_levelPosition.Y = ...;
            return m_levelPosition;
        }
    }
}
编辑
对于
LevelPosition
属性也应该这样做。请参阅修改的源代码

(*)

Tim Schmelter向我指出,他详细讨论了实例化对象的影响。我重新表述了我最初的一句话:创建对象总是很昂贵的。虽然创建对象并不总是一项昂贵的操作,但在某些情况下它仍可能降低性能。

据我所知,您应该避免在XNA中从堆中分配大量对象,因为这会导致性能下降。但是由于
Vector2
是一个
struct
,我们在这里没有在堆上分配任何东西,所以这不应该是这里的问题

现在,如果您在性能关键型应用程序(如游戏)中有严格的循环,那么您必须始终考虑性能,这是不可能的

如果我们查看
LevelPosition
的代码,您将调用
WorldPosition
的getter两次,可能还会调用更多的getter。
WorldPosition
的getter可能很少调用其他getter。(如果没有源代码,很难说到底发生了什么,因为getter调用和字段访问看起来完全一样。)

对getter的调用,实际上只是对一个特殊方法的调用,通常非常快,如果编译器决定使用内联,则可以更快。但是所有的调用加在一起,特别是在循环中调用它们时

解决这个问题的办法是某种缓存。一种选择是将
LevelPosition
设置为一个字段,并设计一个系统在必要时对其进行更新。这可能会起作用,但如果您需要比阅读更频繁地更新它,它实际上也可能会影响性能

另一种解决方案是,正如您所发现的,将结果缓存在局部变量中。如果您知道这是正确的,即属性的值在循环执行期间不会改变,那么这太棒了!你解决了你的性能问题,你只需要一行代码就可以做到,这对任何程序员来说都很容易理解。你还想要什么

让我重申一下。您找到了性能问题的解决方案:

  • 工作
  • 它易于实现
  • 很容易理解

  • 我认为这样的解决方案很难击败。

    Vector2
    a
    class
    ?这里并没有太多的代码,但看起来它可能(应该?)是一个
    结构
    ,在这种情况下,它的性能应该更好。在任何情况下,你提到的修复都是一个完全有效的优化,因为你知道到底是什么让你慢下来了。哦,对不起。我在XNA框架中工作,我应该提到。你真的需要做2500次吗?它不能被削减到例如可见区域吗?事实上,我已经削减到可见区域。我正在从基于平铺的游戏中绘制平铺,由玩家位置偏移。如果属性的返回值不变,并且性能测试表明调用一次并将该值放入本地变量会更快,那么请务必这样做!订阅可能会起作用,但每次我遇到类似情况时,这不是都会带来很大的开销吗?性能开销还是编码开销?我怀疑这是性能开销,因为您无论如何都需要更新这些值。在编码方面。。。当然是这样。也许你可以使用一些通用的基类来缓解这种情况。我认为这是一个好主意。实际上,它可能比我原来的解决方案提高了性能。非常感谢。我同意你应该能够存储这些值,并且只在必要时更新它们。当谈到速度问题时,对象创建总是加快速度的一个很好的起点。很高兴我能帮上忙。@ThorstenDittmar:你的前提是创建对象总是很昂贵,这太直截了当了。听起来好像你建议尽可能避免使用物体,那么你使用的语言是错误的。@ThorstenDittmar:这只是一个假设(“可能有…”)。好吧,这也是一个非常清楚的答案。我将进一步研究这些解决方案,找出最适合我的解决方案。也谢谢你!