【发布时间】:2016-04-03 05:54:27
【问题描述】:
我正在编写一个模拟,它有一个每帧调用的更新循环。在更新函数中,我有数百万个对象要更新,所以看起来像这样。
public void Update(float deltaTime)
{
Time += deltaTime;
foreach (SimulationObject obj in objects.ToArray())
obj.Update(deltaTime);
}
where objects is
List<SimulationObject> objects = new List<SimulationObject>();
and is populated at program initialization time.
您可能会看到 objects.ToArray() 会在每一帧复制这个巨大的列表,然后该副本会被垃圾收集。这给我带来了巨大的性能问题。运行约 2 分钟,收集到的垃圾达到约 2G。由于某些第三方库正在后台异步修改此对象的列表,因此似乎无法删除 ToArray()。
我想知道是否有减少垃圾收集的好方法,避免复制或重用分配的空间?
我是 C# 新手,并尝试搜索答案,但无法找到。如果这是一个重复的帖子,我很抱歉。
【问题讨论】:
-
仅供参考 .ToArray() 复制集合,尽管集合中的对象没有被复制referencesource.microsoft.com/#System.Core/System/Linq/…
-
@Eminem - 假设
SimulationObject是class(引用类型),而不是struct(值类型)。 -
“这个对象的列表正在后台异步修改” - 通常你要避免在游戏/模拟中使用线程细粒度 i> 诸如此类的操作。考虑使用两个列表——一个pending(一个正在后台处理的)和一个active 列表(用于
Update)。然后在适当的时候翻转它们。 amazon.com/Game-Engine-Architecture-Jason-Gregory/dp/1568814135 -
您也可以借鉴 XNA,其中提出了一些很好的 c# 性能提示,以最大限度地减少 GC 影响(这对于 c# 传统 Xbox 360 游戏尤其重要)。例如,在一个简单的
foreach中有一个可衡量的费用!查看Shawn Hargreave's blog (Microsoft) 和Riemer's XNA Tutorials
标签: c# performance garbage-collection