基本的就不介绍了
都知道是减少创建和销毁,提高性能
为什么频繁创建销毁影响性能
百度半天都没有说清楚,也可能是说了但我没理解到
想明白了,就是浪费时间资源的问题
CPU资源宝贵,创建销毁会占用CPU的资源,减少CPU做其他有效工作的时间。
面试被问到半天没反应过来。我当时只记得有额外信息,忘了内存分配,CPU这些
创建对象,申请内存,会占用CPU资源
《CLR via C#》(第4版)第448页
C#的new操作符导致CLR执行以下步骤:
1.计算类型的字段(以及从基类型继承的字段)所需的字节数。
2.加上对象的开销所需的字节数。类型对象指针和同步块索引,在32位应用程序下,二者都要32位,所以每个对象要增加8字节;在64位应用程序下,二者都要64位,所以每个对象要增加16字节。
3.CLR检查区域中是否有分配对象所需的字节数。如果有,在NextObjPtr指针指向的地址处放入对象,为对象分配的字节会被清零。接着调用类型的构造器,new操作符返回对象引用。返回前NextObjPtr会更新,指向下一个对象放入托管堆时的地址。
销毁对象,回收内存,会占用CPU资源
第449页
CLR使用引用跟踪算法。只关心引用类型的变量,因为只有它们才能引用托管堆上面的对象。所有引用类型的变都量称为根。
CLR开始GC时,首先暂停进程中的所有线程,这样防止线程在CLR在检查期间访问对象并更改其状态。
然后进入GC的标记阶段,CLR遍历堆中的所有对象,将同步块索引字段中的一位设为0。这表明所有对象都应删除。然后CLR检查所有活动根,查看他们引用了哪些对象。这正是引用跟踪GC名称的由来。如果一个根包含null,CLR略过它检查下一个。
任何根如果引用了托管堆上的对象,CLR都会标记那个对象,也就是说将该对象的同步索引块的位设为1。一个对象被标记后,CLR会检查那个对象中的根,标记它们引用的对象。如果发现对象已经标记,就不重新检查对象的字段。这就避免了因为循环引用而产生死循环。
然后进入GC的压缩(compact)阶段。compact以前翻译为碎片整理。CLR对堆中已标记的对象进行压缩,使它们内存位置改变,变成连续的,紧凑的,恢复了引用的“局部化”,减小了应用程序的工作集,从而提高了将来访问这些对象时的性能。压缩意味着托管堆解决了本机(原生)堆的空间碎片化问题。
没有GC的语言回收内存是怎么做的呢
C++中delete和new的所需要的时间,哪个高,为什么 - 开源中国 https://www.oschina.net/question/253717_75423
明月照大江 2012/10/20 05:49
我从《现代操作系统》来看,new分配内存的时候,操作系统从管理内存的链表(先这么定吧)从拿出一块符合要求大小的内存来(不管是最佳适配还是首次适配)最差也是扫描一遍管理内存的链表,而delete操作归还内存空间的时候,还要去寻找和这个被释放的内存地址相近的内存空间,判断他们是否也是空闲的,如果是空闲的还要将他们进行合并,合并成一块连续的空闲空间。为了保证能够充分的利用内存空间,确保在内存分配的时候能快速的找出一个合理的空间,那么在删除的时候是要多花一点时间的。不知道我这个解释对不对。
这似乎又涉及到操作系统,基本全忘了,有空复习
申请内存要CPU计算,回收也要计算,难怪影响性能。