WhiteEngine-专注图形渲染与游戏引擎技术的网站

新浪微薄腾讯微薄

最新碎语:暂无碎语

您的位置:WhiteEngine-专注图形渲染与游戏引擎技术的网站 >C#与Lua> c#程序内存分配

c#程序内存分配

c#程序内存分配


        进程可使用内存数就是操作系统给进程分配的最大地址,一般的32位操作系统提供给用户地址最大都是3g(操作系统自己保留1g),windows由于商业目的,对于个人用户只提供了2g地址,要使用3g扩展需要对系统配置作修改。还有就是intel的32位芯片实际上是支持36位寻址能力的(64g),但是也是出于商业目的对于大部分个人芯片都禁止了这个功能,这个禁止可能是物理上的限制个人用户几乎无法修改。


        而且在操作系统中物理可用内存和进程实际占用内存是有区别的,因为有虚拟地址和交换区这种概念,进程实际使用的内存量远远大于物理可用内存,最简单的一个例子就是声明一个非常大的数组但不存放任何东西,进程启动后占用的物理内存可能很小但是申请的内存地址却是非常大了(虚拟内存数),所以就可能产生这么一种情况:空闲物理内存很多进程所占物理内存很小但却报了内存不够,因为进程可用地址已经完全被分配完了(申请很多,却没有用。所以要JIT,lazy...)。

        有些时候由于代码的问题(确切地说是不了解framework的内存使用机制)也会导致outofmemory,一般占用大内存的情况就是list和hashtable2种结构,而这2种数据结构实际上都是使用数组作为容器存放元素的,由于数组是定长结构所以当达到上限时需要做动态扩容,动态扩容的算法都是2倍当前数组长度,数组本身又是需要连续内存作为保证,如果内存碎片过多就会导致没有连续内存可用,.net的智能垃圾回收器也没办法完全避免内存碎片(可以通过禁止垃圾回收或者降低垃圾回收频率来避免碎片,但是需要手工回收来解决内存增长问题),所以在使用list或者hashtable的时候最好能事先指定需要的最大容量上限,避免到后面因为碎片问题导致outofmemory。比如申请的初始内存块不够大,后期要分配更大内存,在本块内存区后面没有这么大的连续空闲内存,就会outofmemory。

小计:C# List的内存分配

        当List<T>对象的Item元素数量超过了Capacity的数量时,List<T>对象会重新申请一块大小是原来Capacity的两倍的内存空间,然后将当前所有Item元素以及待添加元素复制到新的内存空间中。

        知道了内存分配的原则,接下来就得根据这些原则来采用最优的方法保证有限的内存空间能得到合理的运用。归纳起来主要有如下你点:
1.当实例化一个List<T>对象时,如果能预知其Item元素的大致个数,应该在实例化一个List<T>对象的时候设置其Capacity值为接近于Item元素个数的最小值。这样的话可以避免在像List<T>中添加元素的时候,不断的申请内存与元素的复制。

2.当由于不断的调用Remove方法而导致Item元素的个数远远小于Capacity,就会造成内存的浪费。此时可以调用TrimExcess方法释放多余的内存。


总结:

能用数据解决的问题就用数组去解决,动态集合的使用需要注意Capacity和Remove,不然会导致不恰当的使用内存而带来额外的性能开销和GC回收垃圾。

---

转载请注明本文标题和链接:《c#程序内存分配

发表评论

路人甲 表情
看不清楚?点图切换 Ctrl+Enter快速提交