堆栈是什么?html
在说堆栈以前,先说说内存是神马?程序员
内存:程序在运行的过程,电脑须要不断经过CPU进行计算,这个计算的过程会读取并产生运算的数据,这些数据须要一个存储容器存放。这个容器,这就是内存了。算法
咱们知道C#是强类型语言,每一个变量和常量都有一个类型,即全部的数据都会有一个类型。在.Net中,全部的类型又分为值类型和引用类型。简单介绍一下。数据结构
值类型:使用int,float,struct,enum关键字直接继承自System.ValueType定义的类型。app
引用类型:Class,interface,string,delegate继承自System.Object。大数据
值类型和引用类型有什么区别呐?优化
主要区别在于值类型对象固定大小,引用类型对象能够指向任何类型,没法肯定其大小。所以内存区域分为栈和堆。值类型存储在栈上,引用类型存储在堆上。spa
栈:操做系统会为每条线程分配必定的空间,Windows为1M。在栈上的成员不受GC管理器的控制,直接由操做系统分配。或者理解为存储短时间较小数据块,超出做用域,自动释放。操作系统
堆:主要用来存放引用类型对象,不须要咱们人工去分配和释放,由GC管理器托管。或者理解为存储长期较大数据块,超出做用域并不会被释放,保持被分配的状态。GC会处理未引用的堆内存。线程
不一样于值类型直接在栈中存放值,引用类型还须要在栈中存放一个指向堆中对象的值的地址。
值类型,引用类型区别详见:https://www.cnblogs.com/u3ddjw/p/6756536.html
值类型和引用类型之间能够互转吗?
这个需求,是很常见,因此要说一下。答案是确定的,固然能够,这里就须要提到装箱(值类型===>引用类型),拆箱(引用类型===>值类型)。
装箱:
I.分配堆内存
II.将值类型的实例字段拷贝到新分配的堆内存中
III.返回托管堆中新分配的对象的地址在栈中。这个地址就是一个指向对象的引用。
拆箱:
I.检查对象实例,确保它是给定值类型的一个装箱值。
II.将该值实例复制到值类型变量中。
①GC和堆内存联系
上述说到栈是操做系统实时自动分配释放,不须要咱们去管理。堆内存也是由GC控制管理。可是GC并非实时管理的,是须要经过程序员手动或系统定时触发的。由于GC是一个耗时的操做,可能在有些系统中触发的不合时宜(明显卡顿)。因此,GC也须要优化,须要控制在合事宜的状况触发。好比游戏中咱们须要在切换Loading时触发GC,而在游戏战斗中控制不能被触发。
所以优化GC,就是优化堆内存,就是尽可能减小堆内存,及时回收堆内存。
②GC是什么?
GC即(Gabarage Collector,垃圾回收器),归属于CLR(公共语言运行时,能够理解为.Net虚拟机),专门用于回收托管堆内存的
③GC如何释放堆内存的?
GC清理堆时,GC收集器会经过必定的算法清理堆中的对象,而且版本不一样算法也不一样。标记-压缩算法:经过一个图的数据结构来收集对象的根,这个根就是引用地址。能够理解为指向托管堆的关系线。当触发这个算法时,会检查图中的每一个根是否可达,若是可达,则对其标记,而后在堆上找到剩余没有标记的对象进行删除,这样,
那些再也不使用的堆中对象就删除了。
为了优化内存结构,减小在图中搜索的成本,GC机制又为每一个托管堆对象定义了一个属性,将每一个对象分为三个等级,0代,1代,2代。
每当new一个对象的时候,该对象会被定义为第0代,当GC开始回收的时候,先从第0代开始,在这样一次回收动做以后,0代没有被回收的对象则被定义为第1代,当回收第1代的时候,第1代中没有被清理的对象会被定义为第2代。
CLR会为0/1/2代选择一个预算的容量,0代一般为256k-4mb预算,1代为512-4m,2代不受限制,最大可扩充至操做系统的整个内存空间。代数越长说明这个对象经历了回收的次数越多,那就意味着该对象是最不容易被清除的。这种分代的思想将对象分割成新老对象,进而配对不一样的清除条件,这种巧妙的思想避免了直接清理整个堆(卡顿后果)。
扩展说明:
好比Unity采用贝姆垃圾回收机制与.Net垃圾回收器相比一直有很大的限制。
I.贝姆垃圾回收:无分代\并行,执行时全部线程阻塞;每次标记都会访问全部可达的对象(穷举搜索垃圾)。这种方式极有可能在短期形成帧率降低,影响玩家体验。
II.分代回收:效率高不少。
参考:https://1996v.cnblogs.com/p/9037603.html?from=timeline&isappinstalled=0