Met*_*ile 6 c# garbage-collection yield-return
我正在使用XNA开发Xbox 360游戏.我真的很想yield return在几个地方使用C#的构造,但它似乎造成了很多垃圾.看看这段代码:
class ComponentPool<T> where T : DrawableGameComponent
{
List<T> preallocatedComponents;
public IEnumerable<T> Components
{
get
{
foreach (T component in this.preallocatedComponents)
{
// Enabled often changes during iteration over Components
// for example, it's not uncommon for bullet components to get
// disabled during collision testing
// sorry I didn't make that clear originally
if (component.Enabled)
{
yield return component;
}
}
}
}
...
Run Code Online (Sandbox Code Playgroud)
我到处都使用这些组件池- 用于子弹,敌人,爆炸; 任何无数和短暂的.我经常需要遍历他们的内容,而我只对活跃的组件(即Enabled == true)感兴趣,因此Components属性的行为.
目前,在使用这种技术时,我看到每秒大约800K的额外垃圾.这是可以避免的吗?还有其他方法可以使用yield return吗?
编辑:我发现这个问题关于如何迭代资源池而不创建垃圾的更广泛的问题.许多评论者都不屑一顾,显然不理解Compact Framework的局限性,但这位评论者更加同情并建议创建一个迭代池.这是我将要使用的解决方案.
编译器对迭代器的实现确实使用了类对象,并且使用(例如,使用 foreach)实现的迭代器yield return确实会导致分配内存。在事情的计划中,这很少是一个问题,因为要么在迭代时完成大量工作,要么在迭代时分配更多内存来做其他事情。
为了使迭代器分配的内存成为问题,您的应用程序必须是数据结构密集型的,并且您的算法必须在不分配任何内存的情况下对对象进行操作。想想类似的生命游戏。突然之间,迭代本身就变得不堪重负。当迭代分配内存时,可以分配大量内存。
如果您的应用程序符合此配置文件(并且仅当),那么您应该遵循的第一条规则是:
例如,如果您有一个类似数组或列表的数据结构,那么您已经公开了索引器属性和计数属性,因此客户端可以简单地使用 for 循环,而不是在迭代器中使用 foreach。这是减少 GC 的“轻松赚钱”,它不会使您的代码变得丑陋或臃肿,只是有点不太优雅。
您应该遵循的第二个原则是:
| 归档时间: |
|
| 查看次数: |
2034 次 |
| 最近记录: |