2009-10-17 47 views
7

我正在使用XNA为xbox360制作游戏。在Xbox上,垃圾收集器与PC上的垃圾收集器相比性能相当差劲,因此将垃圾产生量降到最低对于顺利执行游戏至关重要。使用委托创建垃圾

我记得读过一次,调用委托创建垃圾,但现在我的生活找不到任何引用创建垃圾的代表。我只是做了这个或代表杂乱?

如果代表很凌乱,建议解决方法的奖励点。

public delegate T GetValue<T>(T value, T[] args); 

public static T Transaction<T>(GetValue<T> calculate, ref T value, params T[] args) where T : class 
{ 
    T newValue = calculate(value, args); 
    return foo(newValue); 
} 

我的代码看起来依稀像此刻,我能想到的唯一的解决办法,以摆脱自己代表的是在继承的接口IValueCalculator一个类来传递,然后我可以调用该方法界面,虽然不是很整洁!

+0

代表应该是非常小的,不应该创建当你执行它们时,会有很多垃圾。 (如果他们创建垃圾,它应该是每个都有字节的拳头)。传递接口引用并在完成时不使用接口引用也会产生垃圾。 – CodingBarfield

回答

10

委托本身就是一个对象,所以如果你创建一个委托,也许是一个匿名方法,并且给它一些其他的方法来执行,并且不会存储这个委托以备将来参考,那么是的,会产生垃圾。

举例来说,这样的:

collection.ForEach(delegate(T item) 
{ 
    // do something with item 
}); 

在这种情况下,创建一个新的委托对象,但超出了调用ForEach它不被引用,因而有资格进行垃圾回收。

但是,调用委托本身并不产生垃圾,比调用任何其他同类型的方法更重要。例如,如果您调用一个采用Object参数的委托,传入一个Int32值,则此值将被装箱,但如果您以同样的方式调用常规方法,则会发生这种情况。

所以使用委托应该没问题,但过度创建委托对象将是一个问题。


编辑:内存管理Xbox和XNA一篇好文章是在这里:Managed Code Performance on Xbox 360 for XNA: Part 2 - GC and Tools。请注意以下引用:

那么如何控制GC延迟?与设备的NetCF一样,Xbox GC也是非代人的。这意味着每个集合都是托管堆上的完整集合。因此,我们发现GC延迟与活动对象的数量大致成线性关系......然后将堆压缩的成本添加到此。我们的基准测试表明,深层目标层次与浅层目标层次之间的差异可以忽略不计,因此它主要是重要的对象数量。与大件物品相比,小物件往往处理起来要便宜一些。

正如你所看到的,尽量避免创建大量不必要的对象,你应该更好。

+0

我明白了,这很好理解,尽管尝试使用代表而不创建任何(加载时除外)将会很有趣。 – Martin

+1

几乎所有在C#中的东西都会以这种方式创建垃圾。我不会建议避免使用短期引用。 –

+3

通常情况下我都不会,但是在Xbox上,如果你可以推迟GC(即使运行频率较低)而没有不良影响,那么在Xbox上,如果你使用XNA平台,这真的是一个好主意,因为它会*游戏玩法,如果它经常发生。因此,要意识到什么是GC的贡献,以及何时做到这一点,如果您想解决这个问题,这是一个好主意。例如,在我展示的代码中,如果您多次运行ForEach循环,经常可能应该将代理存储在某个变量中,如果这样做不会改变行为。游戏优化通常与普通桌面DB应用程序不同。 –

14

在桌面环境垃圾实际上是免费的。有什么你想担心的是你正在生产多少非垃圾。请记住垃圾收集器的工作原理:它首先标记所有已知对象,然后清除所有活动对象上的标记并压缩活动对象。昂贵的一步是“取消对活体物件的标记”。摧毁垃圾便宜;它会识别昂贵的活动对象,并且成本取决于您拥有的活动对象的数量(以及参考拓扑的复杂性),而不取决于您拥有的死对象的数量。

然而,XBOX和其他紧凑型框架,垃圾收集器相当频繁运行,并且运行更经常地创建新的分配时,所以是的,你是正确的担心也产生垃圾。您既想保持住一套小(以使收集便宜),而不是进行新的分配(因为触发集合。)

创建委托不分配内存,但调用一个什么不仅仅是在一个类上调用一个名为Invoke的方法。委托并不仅仅是一个名为Invoke的类,它在调用时会立即调用另一个方法。

无论如何,如果你有问题的内存性能再到做正确的事情是走出内存分析器,并用它来分析你的程序。随意地转身想知道这是不是分配记忆就像试图用指甲剪去除你的花园;这需要花费很多时间,并没有真正实现你的目标。使用分析器分析您的性能并查看问题出在哪里,然后修复它们。

+0

我倾向于同意你的看法,我并不十分担心垃圾 - 我只是想知道! 但是,你确定这是在收藏家是非世代的Xbox的情况? – Martin

+0

即使它不是世代相传的,它仍然是标志性的。 –

+2

Xbox XNA GC的性能与活/死对象的数量有关,所以是的,尽量减少对象的总数。是的,使用内存分析器来确定你是否真的有问题。 –

1

委托创建会产生垃圾,正如其他人已经注意到的那样。

在你的例子中,使用params参数也可能会产生垃圾。

考虑提供重载而不使用params关键字。

这就是为什么有不同数量的参数重载通常在库方法存在使用params关键字的一个沿着原因:

String.Format Method (String, Object[])

Format Method (String, Object) 
Format Method (String, Object[]) 
... 
Format Method (String, Object, Object) 
Format Method (String, Object, Object, Object)