首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >List.Clear();vs List<T> =新的List<T>();垃圾收集性能

List.Clear();vs List<T> =新的List<T>();垃圾收集性能
EN

Stack Overflow用户
提问于 2018-06-17 10:00:13
回答 1查看 1.8K关注 0票数 4

我正在用大量的人工智能做游戏,注意到我的垃圾收集器每秒收集物体3-4次,这对性能非常不利,并且在帧速率下降之前,敌人的数量限制在120以下。我对代码进行了剖析,发现罪魁祸首是我的碰撞检测代码,其中我有一个函数被多次调用--一个正在生成轴上投影列表的框架。密码就像

代码语言:javascript
复制
public List<Vector2> foo()
{
    List<Vector2> projections = new List<Vector2>();

    // Calculate and return projections
}

还有一些其他函数创建了新列表,每个调用都创建了新的列表,我切换了新列表的生成,每个函数调用都倾向于将vector2s列表存储为类的一个字段,这样我就不会调用每个函数调用的新列表。这将垃圾收集调用从每秒3-4次减少到每10-20秒一次,允许我在帧速率下降之前在地图上得到400-500个敌人。

新的职能应该是:

代码语言:javascript
复制
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()时,垃圾收集量急剧减少,还有其他的事情发生。下面是我用来理解列表项目发生了什么的链接。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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,我相信-所以:没有什么可收集的!

那真的可以加起来!

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50895560

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档