我正在用大量的人工智能做游戏,注意到我的垃圾收集器每秒收集物体3-4次,这对性能非常不利,并且在帧速率下降之前,敌人的数量限制在120以下。我对代码进行了剖析,发现罪魁祸首是我的碰撞检测代码,其中我有一个函数被多次调用--一个正在生成轴上投影列表的框架。密码就像
public List<Vector2> foo()
{
List<Vector2> projections = new List<Vector2>();
// Calculate and return projections
}还有一些其他函数创建了新列表,每个调用都创建了新的列表,我切换了新列表的生成,每个函数调用都倾向于将vector2s列表存储为类的一个字段,这样我就不会调用每个函数调用的新列表。这将垃圾收集调用从每秒3-4次减少到每10-20秒一次,允许我在帧速率下降之前在地图上得到400-500个敌人。
新的职能应该是:
public List<Vector2> foo()
{
// projections is now a field of this class so we just clear it each function call
projections.Clear();
// Calculate and return projections
}我的问题是,为什么List.Clear方法产生的垃圾回收比List = new ()少得多?当您调用clear时,我已经对列表中的项进行了一些研究,当它们不再具有引用时,它们似乎也应该被垃圾收集,所以我的项目是在函数中创建的--所以当该函数退出并在下一次调用时清除该列表时,不也应该垃圾收集前面的项吗?
我的理解是,清除的项目应该被垃圾收集,就像我调用List = new时一样。显然,当我切换到List.Clear()时,垃圾收集量急剧减少,还有其他的事情发生。下面是我用来理解列表项目发生了什么的链接。
发布于 2018-06-17 11:07:43
清除列表时,只需将计数设置为0,并删除现有内容(如果旧对象是引用类型,则旧对象可能是可收集的)。现有的缓冲区(T[])是保留的,可以在下一组中重用。我猜每个帧的投影数大致相同,这意味着可以永远使用相同的数组
但是:如果您新建它,那么将分配一个新的默认大小的缓冲区--它开始于大约10或20,IIRC (编辑:它现在看起来是4)。当您添加(Add)项时,当它没有空间时,它将不得不调整缓冲区的大小(它使用加倍算法,所以当您添加第21项时,它将加倍到40,等等)。如果您有大量的投影,这可能意味着分配(和重拷贝)很多次-所以您可以分配一组数组,最终被丢弃.当然还有一个列表对象。
这些丢弃的“当它满的时候加倍”缓冲区大小为4,8,16,32,64,128,256,512,1024等等,加上实际的列表对象本身,你看到的是被收集的,而不是你的游戏对象。
在particlar:Vector2是一个struct,我相信-所以:没有什么可收集的!
那真的可以加起来!
https://stackoverflow.com/questions/50895560
复制相似问题