最近我一直在玩XNA,我也一直在阅读游戏中垃圾收集的相关内容。我想我已经做了一个合理的工作,通过使用池并减少对foreach的依赖来减少垃圾数量。如何从另一个集合中生成一个游戏实体的集合而不会产生垃圾?
现在我有我的基础游戏实体存储在一个KeyedCollection中,它允许我遍历所有实体(如列表)并通过键(如字典)引用实体。
我希望能够查询我的集合并返回另一个集合而不会产生垃圾每个查询。我在下面列出,因为我觉得我在编码他们我在更好地解释这一概念的样本...
/// <summary>
/// Defines a sample entity.
/// </summary>
public class SampleEntity
{
public uint Id;
public Vector2 Position;
}
/// <summary>
/// Defines a collection of sample entities.
/// </summary>
public class EntityCollection : KeyedCollection<uint, SampleEntity>
{
/// <summary>
/// Return the key for the supplied item.
/// </summary>
protected override uint GetKeyForItem(SampleEntity item)
{
return item.Id;
}
}
/// <summary>
/// Defines the sample game class.
/// </summary>
public class GameSample
{
/// <summary>
/// Create a new instance of the GameSample class.
/// </summary>
public GameSample()
{
Entities = new EntityCollection();
}
/// <summary>
/// Get the collection of game entities.
/// </summary>
public EntityCollection Entities { get; private set; }
/// <summary>
/// Return the collection of entities within a radius of the supplied point.
/// </summary>
public List<SampleEntity> Query(Vector2 center, float radius)
{
List<SampleEntity> results = new List<SampleEntity>() // BAD, BAD, BAD!!!!!
//
// add the entities to the results collection
//
return results;
}
}
这(过分简化的)例子将产生大量的垃圾,因为赫克它会在每次调用时创建一个新的List对象。我也玩过创建一个全球结果列表并清除每个电话,但看起来很难看。
/// <summary>
/// Return the collection of entities within a radius of the specified point.
/// </summary>
public List<SampleEntity> Query(Vector2 center, float radius)
{
_globalResults.Clear();
//
// add the entities to the global results collection
//
return _globalResults;
}
我是否错过了什么?有没有更好的解决方案,我只是不知道。
“我认为我已经做了一个减少垃圾量的合理工作” - 如果您还没有:您应该使用CLR Profiler,那么您肯定会知道*。 – 2010-08-20 13:32:39
很难说不知道“将实体添加到结果集合”里面的逻辑,但我会说这很有可能是收益回报是你的朋友。 – 2010-08-20 13:35:49
@Andrew:这个游戏还不够远,从探查器获得很多有用的信息,但是感谢你指引我走向CLR探查器。 @Nate:不幸的是yield关键字也会产生垃圾,与我的示例类似。它为每个函数调用创建一个新的IEnumerable对象。 –
Pixelfish
2010-08-20 13:48:37