gpt4 book ai didi

c# - C#'s ` yield return` 为我制造了很多垃圾。有救吗?

转载 作者:太空狗 更新时间:2023-10-29 21:41:41 25 4
gpt4 key购买 nike

我正在使用 XNA 开发 Xbox 360 游戏。我真的想在几个地方使用 C# 的 yield return 构造,但它似乎会产生很多垃圾。看看这段代码:

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;
}
}
}
}
...

到处都使用这些组件池——用于子弹、敌人、爆炸;任何数量众多且短暂的事物。我经常需要遍历它们的内容,而且我只对事件的组件感兴趣(即 Enabled == true),因此 Components 的行为属性(property)。

目前,在使用此技术时,我发现每秒大约有 800K 的额外垃圾。这是可以避免的吗?有没有其他方法可以使用 yield return

编辑:我找到了 this question关于如何在不产生垃圾的情况下迭代资源池的更广泛问题。许多评论者不屑一顾,显然不理解紧凑框架的局限性,但是this commenter更有同情心,并建议创建一个迭代器池。这就是我要使用的解决方案。

最佳答案

编译器对迭代器的实现确实使用了类对象,并且使用(例如 foreach)用 yield return 实现的迭代器确实会导致分配内存。在事物的计划中,这很少成为问题,因为在迭代时完成了大量工作,或者在迭代时分配了相当多的内存来做其他事情。

为了让迭代器分配的内存成为一个问题,您的应用程序必须是数据结构密集型的,并且您的算法必须在不分配任何内存的情况下对对象进行操作。想想 Game of Life类似的东西。突然间,迭代本身压倒了一切。当迭代分配内存时,可以分配大量内存。

如果您的应用程序符合此配置文件(且仅当),那么您应该遵循的第一条规则是:

  • 当有更简单的迭代概念可用时,避免在内部循环中使用迭代器

例如,如果您有一个类似数组或列表的数据结构,您已经公开了一个索引器属性和一个计数属性,因此客户可以简单地使用 for 循环而不是将 foreach 与您的迭代器一起使用。这是减少 GC 的“轻松赚钱”,它不会让您的代码变得丑陋或臃肿,只是不够优雅。

您应该遵循的第二个原则是:

  • 测量内存分配,看看何时何地应该使用第一条规则

关于c# - C#'s ` yield return` 为我制造了很多垃圾。有救吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5838177/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com