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方法釋放多余的內存。
c# 線程池 http://wenku.baidu.com/view/a6f14375f46527d3240ce01b.html
=====================================
Chat Question: Memory Limits for 32-bit and 64-bit processes
During our recent blog chat, there were a number of topics that were asked about and I am going to expand on some of them. The first one is the memory limits for different processes.
This really depends on a few different things. The architecture of the process (32-bit or 64-bit) and also the architecture of the Operating System the process is running on. For 32-bit it also depends if you use the /3GB switch or not.
So I broke this up based on these things into the table below, this is the maximum amount of memory available for the process assuming you have that much RAM and Pagefile space.
|
32-bit OS |
64-bit OS |
32-bit process |
2 GB |
4 GB |
32-bit process with /3GB |
3 GB |
N/A |
64-bit process |
N/A |
16 TB |
These process numbers are contingent on how much RAM and disk space you have, so if you have 4 GB of RAM(內存) and 4 GB Pagefile(虛擬內存), the total memory of all running processes can’t be greater then 8 GB.
Note: If you let Windows manage your Pagefile size, when you hit this limit, Windows will try to grow your Pagefile as long as there is disk space available.
For the amount a .NET application will use before we can expect to see out of memory, those numbers are:
|
32-bit OS |
64-bit OS |
32-bit process |
800-1200 MB |
2800 MB |
32-bit process with /3GB |
1800 MB |
N/A |
64-bit process |
N/A |
2800 MB if using a 4 GB process or more if more RAM (around 70% of RAM + Pagefile) |
Keep in mind that although a .NET process can grow this large, if the process is multiple GB in size, it can become very difficult for the Garage Collector to keep up with the memory as Generation 2 will become very large. I’ll talk about the generations more in an upcoming post.
Hopefully that will clear up how much memory each one uses.
Keep checking the RECAP- ASP.NET Blog Chat to see other topics that Tess or I write about.